我为我的自定义Either类型编写了一个名为Or的Or实例,它运行得很好,如下所示:
data Or a b = First a
| Second b
deriving (Eq, Show)
instance Functor (Or a) where
fmap _ (First x) = First x
fmap f (Second b) = Second $ f b然而,当我使用as模式时,程序不再打打字机了:
instance Functor (Or a) where
fmap _ first@(First _) = first
fmap f (Second b) = Second $ f b错误信息:
error:
• Couldn't match type ‘a1’ with ‘b’
‘a1’ is a rigid type variable bound by
the type signature for:
fmap :: forall a1 b. (a1 -> b) -> Or a a1 -> Or a b
at /home/me/haskell/functors/src/Lib.hs:139:3-6
‘b’ is a rigid type variable bound by
the type signature for:
fmap :: forall a1 b. (a1 -> b) -> Or a a1 -> Or a b
at /home/me/haskell/functors/src/Lib.hs:139:3-6
Expected type: Or a b
Actual type: Or a a1
• In the expression: first
In an equation for ‘fmap’: fmap _ first@(First _) = first
In the instance declaration for ‘Functor (Or a)’
• Relevant bindings include
first :: Or a a1
(bound at /home/me/haskell/functors/src/Lib.hs:139:10)
fmap :: (a1 -> b) -> Or a a1 -> Or a b
(bound at /home/me/haskell/functors/src/Lib.hs:139:3)
|
139 | fmap _ first@(First _) = first
| ^^^^^这让我感到惊讶,因为我假设First x和first具有相同的类型。
这种类型错误的原因是什么?
我用的是GHC 8.2.2。
发布于 2018-03-26 18:48:47
你偶然发现了一个微妙的小错误。看看First的类型。
First :: a -> Or a b现在,我们通常省略forall量词,但是对于所有的a和b来说都是如此。这将是很重要的。
fmap1 _ (First x) = First x
fmap2 _ first @ (First _) = first让我们应用一些显式类型签名。(下面不是实际的Haskell代码,因为您不能在模式中具有类型签名。但它说明了这一点。)
fmap1 :: (b -> c) -> Or a b -> Or a c
fmap1 _ ((First :: a -> Or a b) x) = (First :: a -> Or a c) x
fmap2 :: (b -> c) -> Or a b -> Or a c
fmap2 _ (first :: Or a b) @ (First _) = (first :: Or a b)因此,在fmap2中,first有Or a b类型,但是您需要一个Or a c才能使一切正常工作。在第一个例子中,看起来您只是不应用,然后再应用First,但实际上应用的是一个不同的(但相关的)函数。这就像你如何做show 1和show "A"一样。这是对两个不同函数的两个不同调用,它们恰好共享名称show。在你的例子中,这是一个类似的概念。您正在提取的First是一个Or a b,但是您在右侧构造的First是一个Or a c。
https://stackoverflow.com/questions/49498426
复制相似问题