所以我有这些数据类型:
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 函数方面感到迷茫..
fmap
具有以下签名:
fmap :: Functor f => (a -> b) -> f a -> f b
所以这意味着它将 - 给定一个从a
映射到b
的函数,产生一个将Stuff a
映射到Stuff b
的函数。但是Stuff
的属性不是a
的,因此您不能直接对参数调用f
。
所以这可能意味着你想先把StuffPart a
做成Functor
。例如:
instance Functor StuffPart where
fmapf (Add x y) = Add (f x) (fmapf y)
fmap_ End = End
看起来StuffPart
是列表的自定义定义([]
)。
然后我们可以简单地定义:
instance Functor Stuff where
fmap f (Stuff x y) = Stuff (fmapf x) (fmapf 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 (foox) (fooy)
wherefoo(Add x y) = Add (f x) (fooy)
fooEnd = End
您还需要一个用于StuffPart
的Functor
实例:
instance Functor Stuff where
fmap f (Stuff p1 p2) = Stuff (fmap f p1) (fmap f p2)
instance Functor StuffPart where
fmap f (Add x sp) = Add (f x) (fmap f sp)
fmap f End = End