功能无法匹配类型

时间:2012-05-22 20:02:47

标签: haskell types type-inference

我的功能如下:

    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的定义更通用(在foo中绑定到某种类型)?

感谢您的帮助!

2 个答案:

答案 0 :(得分:9)

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

和<{p>中的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如何推断类型。

答案 1 :(得分:2)

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