加载时没有错误:
data Const c a = Const c
instance Functor (Const c) where
fmap _ (Const v) = Const v
......但是这个
data Const' c a = Const' c
instance Functor (Const' c) where
fmap _ cv = cv
...失败了:
Couldn't match type `a' with `b'
`a' is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Const' c a -> Const' c b
at test.hs:4:5
`b' is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Const' c a -> Const' c b
at test.hs:4:5
Expected type: Const' c b
Actual type: Const' c a
In the expression: cv
In an equation for `fmap': fmap _ cv = cv
In the instance declaration for `Functor (Const' c)'
我不明白这个错误。为什么编译器不能推断出cv
的类型是Const' c
?鉴于声明的其余部分以及fmap
的定义?
答案 0 :(得分:9)
如果你想要完全明确,你可以写
{-# LANGUAGE ScopedTypeVariables, InstanceSigs #-}
data Const c a = Const c
instance Functor (Const c) where
fmap :: forall a b. (a -> b) -> Const c a -> Const c b
fmap _ (Const v :: Const c a) = Const v :: Const c b
哪个有点满口。 : - )
forall a b.
将a
和b
纳入范围,以便在定义中引用它们。这由ScopedTypeVariables
启用。 InstanceSigs
允许我们首先编写fmap
的签名(通常必须从类中推断出来,因此我们无处可从中获取类型变量名称)
答案 1 :(得分:7)
cv
属于Const' c a
类型,因此它也不能属于Const' c b
类型(除非a ~ b
)。但是,Const v
和Const v
可以是不同类型的。
另一种看待它的方式是fmap _ cv = cv
等同于fmap _ = id
,其类型为Const' c a -> Const' c a
,但fmap _
必须属于Const' c a -> Const' c b
类型}。