我遇到了函数无法进行类型检查的情况,除非我明确地在其类型签名的开头添加了forall.
有问题的功能是:
test :: (Typeable a) => a -> a
test x
| typeOf (undefined :: a) == typeOf (undefined :: a) = x
| otherwise = x
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
所以它没有统一两种类型的未定义值.但是,如果我在前面添加一个forall:
test :: forall a. (Typeable a) => a -> a
test x
| typeOf (undefined :: a) == typeOf (undefined :: a) = x
| otherwise = x
Run Code Online (Sandbox Code Playgroud)
它汇编很好.这是在GHC 7.4.2中使用的
{-# LANGUAGE GADTs, StandaloneDeriving, DeriveDataTypeable,
ScopedTypeVariables, FlexibleInstances, UndecidableInstances,
Rank2Types #-}
Run Code Online (Sandbox Code Playgroud)
我的印象是,在类型签名中省略"forall"相当于在所有相关类型变量上隐含地附加了foralls(如GHC文档中所述:http://www.haskell.org/ghc/docs/ 7.4.2/html/users_guide/other-type-extensions.html).为什么第一个代码片段不进行类型检查,而第二个代码片段呢?
该ScopedTypeVariables扩展为顶级forall量词添加了语义值.它是在绑定体上提供类型变量的范围.
如果没有forall,该类型变量a第3行是一个不同类型的变量比所述a第1行的错误消息指示这通过标记他们a0和a1.如果没有相同的类型,第3行的类型是模糊的,因为它完全不受约束.