22

数値リテラルにはポリモーフィック型があります。

*Main> :t 3
3 :: (Num t) => t

しかし、変数をそのようなリテラルにバインドすると、ポリモーフィズムは失われます。

x = 3
...
*Main> :t x
x :: Integer

一方、関数を定義すると、もちろん多形になります。

f x = 3
...
*Main> :t f
f :: (Num t1) => t -> t1

型署名を提供して、x残差が多形であることを確認できます。

x :: Num a => a
x = 3
...
*Main> :t x
x :: (Num a) => a

しかし、なぜこれが必要なのですか?ポリモーフィック型が推測されないのはなぜですか?

4

2 に答える 2

23

これは、パラメーターなしで定義され、明示的な型注釈がないすべての値が単相型である必要があることを示す単相制限です。この制限は、を使用してghcおよびghciで無効にできます-XNoMonomorphismRestriction

制限の理由は、この制限long_calculation 42がないと2回評価されるのに対し、ほとんどの人はおそらく1回だけ評価されることを期待/望んでいるためです。

longCalculation :: Num a => a -> a
longCalculation = ...

x = longCalculation 42

main = print $ x + x
于 2010-11-14T20:24:34.967 に答える
19

sepp2kの答えを少し拡張すると、次のものをコンパイルしようとすると(またはGHCiにロードしようとすると)、エラーが発生します。

import Data.List (sort)
f = head . sort

これは、クラス制約(によって導入された)がありますが、明示的な引数がないため、単相制限の違反です。制約にが含まsortれていると(やや不思議なことに)言われています。Ambiguous type variableOrd a

あなたの例( )にも同様に曖昧な型変数がありますが、 Haskellの「デフォルト」ルールlet x = 3によって保存されているため、同じエラーは発生しません。

モジュール全体の型推論が完了したときに残る単形型変数は、あいまいであると見なされ、デフォルトのルール(セクション4.3.4)を使用して特定の型に解決されます。

デフォルトルールの詳細については、この回答を参照してください。重要な点は、特定の数値クラスでのみ機能するため、機能しない場合でもx = 3問題f = sortがないことです。

補足として:x = 3最終的にがのInt代わりにIntegerなりy = 3.0、のRational代わりになりたいDouble場合は、「デフォルト宣言」を使用して、デフォルトのデフォルトルールをオーバーライドできます。

default (Int, Rational)
于 2010-11-14T22:17:42.247 に答える