ここには、acfoltzerに含まれるいくつかのリンクで言及されている別の要因がありますが、ここで明示する価値があるかもしれません。単相制限の影響に遭遇しています。あなたが言う時
let x = 5
変数のトップレベルの定義を作成します。MRは、そのような定義は、型シグネチャを伴わない場合、未解決の型変数に(うまくいけば)適切なデフォルトインスタンスを選択することにより、単形値に特化する必要があると主張しています。対照的に、推論されたタイプを要求するために使用する場合、そのような制限やデフォルトは課されません。それで:t
> :t 3
3 :: (Num t) => t
3
は実際にオーバーロードされているためです。任意の数値タイプで許可されます。デフォルトのルールInteger
はデフォルトの数値タイプとして選択するため、
> let x = 3
> :t x
x :: Integer
しかし、今度はMRをオフにしましょう。
> :set -XNoMonomorphismRestriction
> let y = 3
> :t y
y :: (Num t) => t
MRがない場合、定義は可能な限り多形であり、と同じようにオーバーロードされ3
ます。チェックしてるだけ...
> :t y * (2.5 :: Float)
y * (2.5 :: Float) :: Float
> :t y * (3 :: Int)
y * (3 :: Int) :: Int
多型は、関連するインスタンスで提供されるメソッドy = 3
に応じて、これらの用途に異なる方法で特化されていることに注意してください。つまり、の特定の表現に関連付けられているのではなく、の表現を構築するためのスキームに関連付けられています。素朴に編集された、それはスローのレシピであり、MRの動機として一部の人々が引用しています。fromInteger
Num
y
3
3
私は(地元ではそういうふりをして)、単相性の制限がより小さな悪なのか、より大きな悪なのかについての議論に中立です。私は常にトップレベルの定義の型署名を書いているので、私が達成しようとしていることについて曖昧さはなく、MRは重要ではありません。
型システムがどのように機能するかを学ぼうとするとき、型推論の側面を分離することは本当に役に立ちます。
「計画に従ってください」、特定のユースケースに多態的な定義を特化します。制約解決のかなり堅牢な問題であり、バックチェーンによる基本的な統合とインスタンスの解決が必要です。と
「計画を推測する」、型を一般化して、型シグネチャのない定義にポリモーフィック型スキームを割り当てます。これは非常に脆弱であり、型クラス、上位のポリモーフィズム、 GADT、見知らぬものになります。
最初のものがどのように機能するかを学び、2番目のものが難しい理由を理解するのは良いことです。型推論の奇妙さの多くは、2番目の問題、およびあいまいさに直面したときに有用なデフォルトの動作を提供しようとする単相制限などのヒューリスティックに関連しています。