I've a World datatype that is defined this way:
data World = World
{ resolution :: (Int, Int)
, direction :: Snake_direction
, snake_scale :: Int
, snake :: [(Int, Int)]
, isStuck :: Bool
, gen :: R.StdGen
, food :: (Int, Int)
, superFood :: (Int, Int)
} deriving (Read, Show)
and I want to use a functor that uses fmap over the snake list which is a paramter of the world datatype. I'm struggling with functor syntax
instance Functor (World) where
fmap f (World) = World {fmap f snake}
but the compiler says
error: parse error on input ‘f’
If we inspect the Functor
type class, we see:
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a
{-# MINIMAL fmap #-}
So the kind of f
should be * -> *
, a type with a type parameter. This is not the case here, so we can not declare World
an instance of Functor
. Since the user can use any function f :: a -> b
to map a World a
to a World b
, but there is no World a
at all.
If you still want to make it a Functor
, we can first "upgrade" the World
type such that it has a type parameter:
data World a = World
{ resolution :: (Int, Int)
, direction :: Snake_direction
, snake_scale :: Int
, snake :: [(a, a)]
, isStuck :: Bool
, gen :: R.StdGen
, food :: (Int, Int)
, superFood :: (Int, Int)
} deriving (Read, Show)
then we can define an fmap
as follows:
instance Functor World where
fmap f w = w {snake = fmap (\(x,y) -> (f x, f y)) (snake w)}
or if you want to fmap
over the snake
directly, and not over the coordinates of the snake
:
data World a = World
{ resolution :: (Int, Int)
, direction :: Snake_direction
, snake_scale :: Int
, snake :: a
, isStuck :: Bool
, gen :: R.StdGen
, food :: (Int, Int)
, superFood :: (Int, Int)
} deriving (Read, Show)
then we can define an fmap
as follows:
instance Functor World where
fmap f w = w {snake = f (snake w)}