Reputation: 53
I have data defined as below:
data FGM a = Pure a | GMAction Integer Integer (PlayerMsg -> FGM a)
data PlayerMsg = Guess Integer | Surrender
deriving (Eq, Show)
FGM represents a number guessing game where the 2 integers are the upper and lower bounds, a is the value to be returned in the end, and playermsg is the guess that the player makes.
I would like to make FGM a Functor, so I'm trying to define a fmap for it. Problem is I don't know how do deal with the (PlayerMsg -> FGM a)
part of FGM.
From my understanding of the testcases given, for fmap g
(someFGM), g should only be applied to Pure
, if it's GMAction
, fmap should use PlayerMsg
and generate the next FGM until it reaches a Pure
.
This is what I've tried:
instance Functor FGM where
fmap g (Pure a) = Pure (g a)
fmap g (GMAction upper lower thing) = GMAction upper lower (fmap g (\x -> case (thing x) of
Pure a -> Pure a
GMAction u l t -> GMAction u l t))
But when I try to run test on this I get this error:
Occurs check: cannot construct the infinite type:
b ~ FGM b
Expected type: PlayerMsg -> FGM b
Actual type: PlayerMsg -> b
In the third argument of 'GMAction', namely '(fmap g (\x -> case (thing x) of
Pure a -> Pure a
GMAction u l t -> GMAction u l t))'
In the expression:...
I've also tried
fmap g (GMAction upper lower thing) = GMAction upper lower (fmap g thing)
and got the same error.
I tried to search for examples with data that has a function as parameter like PlayerMsg -> FGM a
, but can't find anything. this is kind of similar but didn't work for me(it's my first failed example). Can someone help me define this fmap or point me at where to learn about this?
Upvotes: 1
Views: 182
Reputation: 153332
GHC's built-in rules for deriving Functor
are enough to handle simple cases like this.
{-# LANGUAGE DeriveFunctor #-}
data FGM a = Pure a | GMAction Integer Integer (PlayerMsg -> FGM a) deriving Functor
data PlayerMsg = Guess Integer | Surrender
deriving (Eq, Show)
Upvotes: 4
Reputation: 8477
Try fmap g (GMAction upper lower thing) = GMAction upper lower ((fmap g) . thing)
. Note the function composition; this is necessary as you need to fmap
over the result of the function.
Upvotes: 5