【问题标题】:function could not match type函数无法匹配类型
【发布时间】:2012-05-29 08:59:25
【问题描述】:

我的功能如下:

    foo :: Int -> a -> [a]
    foo n v = bar n
      where
        bar :: Int -> [a]
        bar n = take n $ repeat v

使用ghci报此错误:

    Couldn't match type `a' with `a1'
          `a' is a rigid type variable bound by
              the type signature for foo :: Int -> a -> [a] at hs99.hs:872:1
          `a1' is a rigid type variable bound by
              the type signature for bar :: Int -> [a1] at hs99.hs:875:9
    Expected type: [a1]
        Actual type: [a]
    In the expression: take n $ repeat v
    In an equation for `bar': bar n = take n $ repeat v

如果去掉bar的类型声明,代码可以正确编译。那么 bar 的正确类型声明是什么?为什么会发生错误,因为 bar 的类型声明比 bar 的定义更通用(绑定到 foo 中的某个类型)?

感谢您的帮助!

【问题讨论】:

    标签: haskell types type-inference


    【解决方案1】:

    a

    foo :: Int -> a -> [a]
    

    还有a

        bar :: Int -> [a]
    

    是同名的不同类型变量。

    要获得您期望的行为,请打开 ScopedTypeVariables 扩展(例如,通过在源文件顶部插入 {-# LANGUAGE ScopedTypeVariables #-}),并将 foo 的类型签名更改为

    foo :: forall a. Int -> a -> [a]
    

    当没有启用ScopedTypeVariables时,就好像你的原始代码是这样写的:

    foo :: forall a. Int -> a -> [a]
    foo n v = bar n
      where
        bar :: forall a. Int -> [a]
        bar n = take n $ repeat v
    

    如果您省略bar 的类型注释,那么说 ghci 隐式使用 ScopedTypeVariables 是不正确的。

    相反,您为 bar 提供的类型注释与 ghci 推断的类型冲突 --- 您断言 bar 具有 ghci 知道它不能具有的类型。

    当你移除类型注解时,你就移除了冲突。

    ScopedTypeVariables 更改您提供的类型注释的含义。它不会影响 ghc 推断类型的方式。

    【讨论】:

    • 感谢您的帮助!正如我所说,如果删除'bar'的类型声明,ghci可以编译代码,这是否意味着ghci在这里隐式使用ScopedTypeVariable?
    • 更清楚一点,作用域类型变量和删除'bar'类型声明都可以使代码编译。只是想知道他们是否在做同样的把戏。
    • 不,它们得到相同的编译代码,但它们得到的结果不同。查看我的编辑。
    • 那么如果没有作用域类型变量,我们可以将 bar 的类型声明为 ghci 推断的类型吗?
    【解决方案2】:

    刚刚发现这个帖子也有很好的解释:http://www.haskell.org/pipermail/haskell-cafe/2008-June/044617.html

    【讨论】:

      猜你喜欢
      • 2020-09-05
      • 1970-01-01
      • 2018-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-28
      • 1970-01-01
      相关资源
      最近更新 更多