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
.