関数の型シグネチャの先頭に明示的に 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)
したがって、未定義の値の 2 つのタイプを統合することに失敗しています。ただし、前に forall a を追加すると、次のようになります。
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 )。最初のコード フラグメントでは型チェックが行われないのに、2 番目のコードでは型チェックが行われるのはなぜですか?