首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型检查失败与as-模式

类型检查失败与as-模式
EN

Stack Overflow用户
提问于 2018-03-26 18:39:43
回答 1查看 50关注 0票数 1

我为我的自定义Either类型编写了一个名为OrOr实例,它运行得很好,如下所示:

代码语言:javascript
复制
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模式时,程序不再打打字机了:

代码语言:javascript
复制
instance Functor (Or a) where
  fmap _ first@(First _) = first
  fmap f (Second b)      = Second $ f b

错误信息:

代码语言:javascript
复制
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 xfirst具有相同的类型。

这种类型错误的原因是什么?

我用的是GHC 8.2.2。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-26 18:48:47

你偶然发现了一个微妙的小错误。看看First的类型。

代码语言:javascript
复制
First :: a -> Or a b

现在,我们通常省略forall量词,但是对于所有的ab来说都是如此。这将是很重要的。

代码语言:javascript
复制
fmap1 _ (First x) = First x

fmap2 _ first @ (First _) = first

让我们应用一些显式类型签名。(下面不是实际的Haskell代码,因为您不能在模式中具有类型签名。但它说明了这一点。)

代码语言:javascript
复制
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中,firstOr a b类型,但是您需要一个Or a c才能使一切正常工作。在第一个例子中,看起来您只是不应用,然后再应用First,但实际上应用的是一个不同的(但相关的)函数。这就像你如何做show 1show "A"一样。这是对两个不同函数的两个不同调用,它们恰好共享名称show。在你的例子中,这是一个类似的概念。您正在提取的First是一个Or a b,但是您在右侧构造的First是一个Or a c

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49498426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档