我刚刚开始学习haskell,我有这个代码,它不会编译:
data Foo a b = Foo a b deriving (Show)
instance Functor (Foo a) where
fmap f (Foo a b) = Foo (f a) b
如果我将fmap实现稍微更改一下,那么它可以工作:
fmap f (Foo a b) = Foo a (f b)
有人可以解释原因吗?
答案 0 :(得分:4)
如果我们有
data Foo a b = Foo a b
和
instance Functor (Foo k) where
然后对于在类型类中定义的所有函数,第一个参数a
是固定的。通过该单行,您告诉全世界对于任何k
,Foo k
将是一个仿函数。但是,这意味着您的第一个参数无法与fmap
映射:
fmap :: Functor f => (a -> b) -> f a -> f b
请记住,我们的仿函数将为Foo k
。所以我们最终会以
fmap :: (a -> b) -> (Foo k) a -> (Foo k) b
-- ^^^^^^^ ^^^^^^^
-- | |
-- +-------+-----+
-- |
-- f from above
当您在第一个参数上使用fmap
时,您创建了fmap
的以下实现:
fmap :: (a -> b) -> (Foo a) z -> (Foo b) z
-- ^^^^^^^ ^^^^^^^
-- | |
-- +-------+-----+
-- |
-- err, those 'f's differ
这就是为什么你的第一个变种不起作用,但后者确实有效。