省略显式forall会产生模糊类型错误

时间:2013-01-01 23:23:39

标签: haskell types ghc

我遇到了一个函数无法进行类型检查的情况,除非我明确地在其类型签名的开头添加了一个forall。

有问题的功能是:

test :: (Typeable a) => a -> a
test x 
    | typeOf (undefined :: a) == typeOf (undefined :: a) = x
    | otherwise = x

GHC对上述内容发出以下警告:

  Ambiguous type variable `a0' in the constraint:
  (Typeable a0) arising from a use of `typeOf'
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `(==)', namely `typeOf (undefined :: a)'
In the expression:
  typeOf (undefined :: a) == typeOf (undefined :: a)
In a stmt of a pattern guard for
               an equation for `test':
  typeOf (undefined :: a) == typeOf (undefined :: a)

Ambiguous type variable `a1' in the constraint:
  (Typeable a1) arising from a use of `typeOf'
Probable fix: add a type signature that fixes these type variable(s)
In the second argument of `(==)', namely `typeOf (undefined :: a)'
In the expression:
  typeOf (undefined :: a) == typeOf (undefined :: a)
In a stmt of a pattern guard for
               an equation for `test':
  typeOf (undefined :: a) == typeOf (undefined :: a)

所以它没有统一两种类型的未定义值。但是,如果我在前面添加一个forall:

test :: forall a. (Typeable a) => a -> a
test x 
    | typeOf (undefined :: a) == typeOf (undefined :: a) = x
    | otherwise = x

编译好。这是在GHC 7.4.2中使用

{-# LANGUAGE GADTs, StandaloneDeriving, DeriveDataTypeable,
ScopedTypeVariables, FlexibleInstances, UndecidableInstances,
Rank2Types #-}

我的印象是,在类型签名中省略“forall”等同于在所有相关类型变量上隐含地附加forall(如GHC文档中所建议的那样:http://www.haskell.org/ghc/docs/7.4.2/html/users_guide/other-type-extensions.html)。为什么第一个代码片段不进行类型检查,而第二个代码片段呢?

1 个答案:

答案 0 :(得分:7)

ScopedTypeVariables扩展名为顶级forall量词添加了语义值。它是在绑定体上提供类型变量的范围。

如果没有forall,第3行的类型变量a是与第1行的a不同的类型变量。错误消息通过标记{{1}来指示这一点。 }和a0。如果没有相同的类型,第3行的类型是不明确的,因为它完全不受约束。