Haskell整数字面量未实现Eq类为何可进行相等比较?
现象原理解释
这个看似矛盾的表现是Haskell的多态值特化规则和数值类型默认规则共同作用的结果,具体逻辑如下:
- 首先
Num类型类确实不强制要求实例实现Eq类,你定义myEqualP时给出的签名Num a => a -> a -> Bool要求该函数支持所有Num实例类型,包括那些没有Eq实现的类型(比如自定义的函数类Num实例),所以编译报错完全符合类型系统规则。 - 关闭单态限制后,
x = 42的类型Num p => p是它的最通用多态类型,含义是「这个值可以被当作任意Num实例类型使用」,而非「这个值的类型只有Num约束,永远不能叠加其他约束」。 - 当执行
x == y时,==运算符要求操作数类型实现Eq类,此时GHC会触发数值类型默认规则:对于模糊的数值类多态类型,默认会优先尝试特化为Integer,其次是Double。而Integer同时实现了Num和Eq两个类,完全满足上下文要求,因此x和y会被自动特化为Integer类型,比较操作自然可以正常执行。
逻辑验证
你可以通过清空默认类型列表验证上述规则,在GHCi中执行如下命令即可复现类型错误:
λ> default () λ> x == y <interactive>:10:1: error: • Ambiguous type variable ‘p0’ arising from a use of ‘print’ prevents the constraint ‘(Show p0)’ from being solved. Probable fix: use a type annotation to specify what ‘p0’ should be. • In a stmt of an interactive GHCi command: print it
此时没有可用的默认类型,GHC无法自动特化出同时满足Num和Eq的具体类型,就会抛出类型歧义错误,和myEqualP的报错逻辑完全一致。
内容的提问来源于stack exchange,提问作者jpmarinier
相关产品推荐
相关产品推荐

