[英]Using functor in haskell
我有一个以这种方式定义的 World 数据类型:
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)
我想使用一个在蛇列表上使用 fmap 的函子,它是世界数据类型的参数。 我正在为函子语法苦苦挣扎
instance Functor (World) where
fmap f (World) = World {fmap f snake}
但编译器说
error: parse error on input ‘f’
另一种选择是不让World
成为函子,因为您真正想要的是一种将函数映射到World
值的一部分的方法。
snakeMap :: ((Int, Int) -> (Int, Int)) -> World -> World
snakeMap f w = w { snake = fmap f (snake w) }
如果我们检查Functor
类型类,我们会看到:
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a
{-# MINIMAL fmap #-}
所以f
的类型应该是* -> *
,一个带有类型参数的类型。 这不是这里的情况,所以我们不能将World
声明为Functor
的实例。 由于用户可以使用任何函数f :: a -> b
将 a World a
映射到World b
,但根本没有World a
。
如果你仍然想把它变成一个Functor
,我们可以先“升级” World
类型,让它有一个类型参数:
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)
那么我们可以定义一个fmap
如下:
instance Functor World where
fmap f w = w {snake = fmap (\(x,y) -> (f x, f y)) (snake w)}
或者如果你想直接在snake
上fmap
,而不是在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)
那么我们可以定义一个fmap
如下:
instance Functor World where
fmap f w = w {snake = f (snake w)}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.