数值型文字具有多态类型:
*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但是为什么这是必要的呢?为什么不推断多态类型?
发布于 2010-11-15 04:24:35
它是monomorphism restriction,它规定所有没有参数和没有显式类型注释的值都应该有一个单态类型。可以使用-XNoMonomorphismRestriction在ghc和ghci中禁用此限制。
限制的原因是,如果没有这个限制,long_calculation 42将被评估两次,而大多数人可能希望/希望它只评估一次:
longCalculation :: Num a => a -> a
longCalculation = ...
x = longCalculation 42
main = print $ x + x发布于 2010-11-15 06:17:42
在Sepp2k的答案上进行一点扩展:如果您尝试编译以下代码(或将其加载到GHCi中),则会得到一个错误:
import Data.List (sort)
f = head . sort这违反了单态限制,因为我们有一个类约束(由sort引入),但是没有显式的参数:我们(有点神秘地)被告知在约束Ord a中有一个Ambiguous type variable。
您的示例(let x = 3)有一个类似的二义性类型变量,但它不会产生相同的错误,因为它是由Haskell's "defaulting" rules保存的
当整个模块的类型推断完成时,剩下的任何单态类型变量都被认为是不明确的,并使用默认规则解析为特定的类型(第4.3.4节)。
有关缺省规则的更多信息,请参见this answer -重要的一点是,它们只适用于某些数值类,所以x = 3是可以的,而f = sort则不是。
附注:如果您希望x = 3最终成为Int而不是Integer,并且y = 3.0成为Rational而不是Double,您可以使用“默认声明”来覆盖默认的默认规则:
default (Int, Rational)https://stackoverflow.com/questions/4179453
复制相似问题