7

我的功能如下:

    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 中的某些类型)?

谢谢你的帮助!

4

2 回答 2

10

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.

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

当您删除类型注释时,您将删除冲突。

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

于 2012-05-22T20:07:53.707 回答
2

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

于 2012-05-23T07:41:38.800 回答