为数据类型定义fmap

时间:2017-06-18 14:00:57

标签: haskell functor

所以我有这些数据类型:

data Stuff a = Stuff (StuffPart a) (StuffPart a) deriving (Show,Eq)
data StuffPart a = Add a (StuffPart a)| End deriving (Show,Eq)

,现在可以为Stuff写一个fmap函数吗?类似的东西:

instance Functor Stuff
  where 
   fmap f (Stuff x y) = Stuff (f x) (f y)

显然我的fmap不起作用,但我能做些什么才能让它工作。 我也试过像:

这样的代码
instance Functor Stuff
  where 
   fmap f (Stuff x y) = Stuff (f x) (fmap f y)

不知怎的,我对fmap函数感到迷茫。

2 个答案:

答案 0 :(得分:6)

fmap有签名:

fmap :: Functor f => (a -> b) -> f a -> f b

这意味着它将 - 给定一个从a映射到b的函数,生成一个将Stuff a映射到Stuff b的函数。但 Stuff的属性不是a s ,因此无法直接调用f参数

这可能意味着您希望首先使StuffPart a成为Functor 。例如:

instance Functor StuffPart where
    fmap f (Add x y) = Add (f x) (fmap f y)
    fmap _ End = End

看起来StuffPart是您对列表的自定义定义([])。

然后我们可以简单地定义:

instance Functor Stuff where
    fmap f (Stuff x y) = Stuff (fmap f x) (fmap f y)

请注意,我们在这里调用的fmap(粗体字)是指我们在上面定义的函数(在Functor StuffPart的上下文中)。

编辑:您 不能StuffPart本身Functor。如果你真的不想这样,你可以简单地定义一个函数foo :: (a -> b) -> StuffPart a -> StuffPart b并调用该函数,但这对我来说实际上看起来像是错误的代码设计,因为如果你以后改变了StuffPart的定义那么部分约Stuff也必须改变,使其变得更难。但如果你真的想要,你可以使用:

instance Functor Stuff where
    fmap f (Stuff x y) = Stuff (foo x) (foo y)
        where foo (Add x y) = Add (f x) (foo y)
              foo End = End

答案 1 :(得分:5)

您还需要Functor的{​​{1}}个实例:

StuffPart