4

私がタイプするとき

:t map length . sum

GHCiに入ると、タイプは次のようになります。

map length . sum :: Num [[a]] => [[[a]]] -> [Int]

ただし、次のファイルtype-test.hsを作成すると

x :: Num [[a]] => [[[a]]] -> [Int]
x = map length . sum

ghcとghciの両方が文句を言います:

type-test.hs:1:1:
    Non type-variable argument in the constraint: Num [[a]]
    (Use -XFlexibleContexts to permit this)
    In the type signature for `x': x :: Num [[a]] => [[[a]]] -> [Int]

FlexibleContextsが有効になっていないのに、なぜghciで(:tを使用して)このタイプを推測できるのですか?

4

5 に答える 5

10

まず、1つのことを明確にしましょう。型を問い合わせるのではなく、GHCi で関数を定義するとどうなるでしょうか?

> let x = map length . sum :: (Num [[a]]) => [[[a]]] -> [Int]
<interactive>:0:9:
    Non type-variable argument in the constraint: Num [[a]]
    (Use -XFlexibleContexts to permit this)
    In an expression type signature: Num [[a]] => [[[a]]] -> [Int]

等々。つまり、同じことです。GHCi に定義の型を推測させたらどうなるでしょうか?

> let x = map length . sum
<interactive>:0:22:
    No instance for (Num [[a0]])
      arising from a use of `sum'
    Possible fix: add an instance declaration for (Num [[a0]])
    In the second argument of `(.)', namely `sum'
    In the expression: map length . sum

これは、型シグネチャのない定義を含むファイルをロードした結果発生するエラーとほぼ同じです。

このすべての結果は何ですか?さて、どの拡張機能が必要かを教えてくれるという事実について考えてみてください。GHC は、デフォルトで型を拒否する場合でも、型が何を意味するかを認識することができます。GHC が使用する拡張機能の組み合わせに応じてまったく異なる型チェッカーを使用するとは考えにくいため、関連する拡張機能が無効になっている以外の理由で問題の型が拒否されていると結論付けるのは簡単に思えます。

GHCiの:tコマンドはコンパイル プロセスの一部ではありません。これは型チェックおよび推論システムへのホットラインであり、仮想コードの型を尋ねることができます。上記のエラー メッセージuse -XFlexibleContexts to permit thisが単にsyntax error in type constraint.


おそらくもっと興味深いのは、推論された型がコンパイラによって問題なく受け入れられる場合もありますが、いくつかの理由のいずれかにより、推論された型を実際には明示的に書き出すことができないということです。

たとえば、モノモーフィズムの制限を無効にする:tと、手動で記述する拡張機能が必要なタイプにもかかわらず、例のタイプが推論されます (言うことと一致します)。

もう 1 つの例はwhere、親関数への多態的な引数を使用する関数定義の節での定義です。それら自身の型はポリモーフィックではなく、外側のスコープで受け取った引数によって決定されますが、親関数のシグネチャの型変数は句のスコープ内にありませんwhere¹。他にも例があるかもしれません。

¹ 親の署名からの型変数は、必要に応じて、ScopedTypeVariables拡張子と明示的なを使用してスコープに入れることができforallます。

于 2011-12-14T16:02:58.193 に答える
7

(これは元の質問には答えませんが、代わりにコードの問題を解決します)

これらのエラーは、記述されたコードがおそらく意図したものではないことを示唆しています。このコード:

map length . sum

は、「数値のリストを取得して合計し、結果の数値の各要素 (??) の長さを計算する」ことを意味します。それは意味がありません。

あなたはおそらく次のことを意味していました:

sum . map length

これは、「リストのリストを取得し、すべての要素の長さを計算し、長さを合計する」ことを意味します。

エラーメッセージ自体が意味することは、issumの型とも呼ばれる数値を返すので、 typeを持つそれを使用しようとすると、コンパイラは型を一致させるためにそれを言おうとし、そこからすべてが下り坂になることです.sumNum n => [n] -> nmap lengthNum m => [[a]] -> [m]n == [[a]]

于 2011-12-14T16:03:53.183 に答える
5

それを見る別の方法:

Haskell は、式が有効な型を持っていたことを[[[a]]] -> [Int]示し[[a]]ますNum

これは、地獄が凍りついたときにあなたと一緒に出かけると言っている女の子のようなものです. 彼女が私と付き合う約束をしたこと文句は言わないだろう。彼女が多かれ少なかれ丁寧な方法でノーと言ったことに気付くでしょう。

于 2011-12-14T17:19:26.493 に答える
1

The problem is that the function is perfectly acceptable, but its most general type is not allowed to be specified by the language grammar. What could ghci do in such circumstances? I can only think of two options, either give a type that can only be specified with some extension enabled, or giving an error. Giving an error without mentioning that it can be fixed by enabling an extension seems not very desirable to me. Just having :t report the inferred most general type is simpler, and quite possibly when the feature was implemented, nobody thought of situations like this.

于 2011-12-14T16:19:28.773 に答える
0

http://haskell.org/ghc/docs/6.12.1/html/users_guide/interactive-evaluation.html#extended-default-rulesを参照

于 2011-12-14T16:02:07.610 に答える