Home > other >  Function that can evaluate multiple games of Rock Paper Scissors at once (using map)
Function that can evaluate multiple games of Rock Paper Scissors at once (using map)

Time:11-29

I have a Function that evaluates the outcome of a single game of rock paper scissors, and returns the players' name like so:

data Symbol = Rock | Paper | Scissors deriving (Eq, Show)
data Outcome = P1 | P2 | Draw deriving (Eq, Show)
evalTurn :: Symbol -> Symbol -> Outcome
evalTurn Rock Scissors = P1
evalTurn Rock Paper = P2
evalTurn Rock Rock = Draw
evalTurn Paper Rock = P1
evalTurn Paper Scissors = P2
evalTurn Paper Paper = Draw
evalTurn Scissors Paper = P1
evalTurn Scissors Rock = P2
evalTurn Scissors Scissors = Draw

type PlayerName = String

data Hand = H PlayerName Symbol deriving (Show)

evalHand :: Hand -> Hand -> Maybe PlayerName
evalHand (H x y) (H a b)
 | evalTurn y b == P1 = Just x
 | evalTurn y b == P2 = Just a
 | evalTurn y b == Draw = Nothing

The above evalHand function works for one game, however my goal is to write an evalMatch function that is able to take an input like this:

  evalMatch [ (H "A" Paper, H "B" Rock )
            , (H "A" Rock , H "B" Paper)
            , (H "A" Rock , H "B" Rock )]

and return the results in a list.:

  == [ Just "A", Just "B",Nothing]

This is what I have so far, but my usage of the map function seems to be off. I'd appreciate it if anyone could guide me in the right direction.

evalMatch :: [(Hand, Hand)] -> [Maybe PlayerName]
evalMatch [(H x y, H a b)]
 | evalTurn y b == P1 = [Just x]
 | evalTurn y b == P2 = [Just a]
 | evalTurn y b == Draw = [Nothing]
evalMatch ((H x y, H a b):xs) = map evalMatch [x:xs]

CodePudding user response:

You already have a function evalHand :: Hand -> Hand -> Maybe PlayerName. One can make use of uncurry :: (a -> b -> c) -> (a, b) -> c to convert a function that takes two parameters, here evalHand into a function that takes a 2-tuple and returns the result by calling the function with the two items of the 2-tuple.

You thus can implement an evalMatch with:

evalMatch :: [(Hand, Hand)] -> [Maybe PlayerName]
evalMatch = map (…)

where I leave filling in the part as an exercise. This expression should work with uncurry and evalHand.

  • Related