4

関数の型シグネチャの先頭に明示的に 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 番目のコードでは型チェックが行われるのはなぜですか?

4

1 に答える 1

7

このScopedTypeVariables拡張機能は、トップレベルのforall量指定子にセマンティックな値を追加します。これは、バインディングの本体に対する型変数のスコープを提供するものです。

それがなければforall、3 行目の型変数は 1 行目の型変数とaは異なりaます。それらが同じタイプでない場合、3 行目のタイプは完全に制約されていないため、あいまいです。a0a1

于 2013-01-01T23:26:30.803 に答える