实现仿函数类型类

时间:2017-03-16 07:40:41

标签: haskell types

我刚刚开始学习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)

有人可以解释原因吗?

1 个答案:

答案 0 :(得分:4)

如果我们有

data Foo a b = Foo a b

instance Functor (Foo k) where

然后对于在类型类中定义的所有函数,第一个参数a是固定的。通过该单行,您告诉全世界对于任何kFoo 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

这就是为什么你的第一个变种不起作用,但后者确实有效。