GHCi中Haskell多态表达式3+5求值机制及默认类型作用疑问
GHCi中
3 + 5的求值机制与默认类型规则解析 一、3 + 5的具体求值流程
首先明确:独立表达式3 + 5会被Haskell语法糖展开为:
fromInteger (3 :: Integer) + fromInteger (5 :: Integer)
它的类型是Num a => a——这是个多态类型,意味着它能适配任何实现了Num类型类的具体类型。
但Haskell只能求值具体类型的值,多态只是类型层面的抽象,所以GHCi处理这个表达式的步骤是:
- 选择具体实例:GHCi会为
Num a => a选择一个具体的Num实例。哪怕你设置了default (),GHCi有个内置的 fallback 逻辑——对无约束的Num a => a类型表达式,默认使用Integer实例。 - 计算具体结果:把表达式实例化成
Integer类型后,就变成了(3 :: Integer) + (5 :: Integer),直接算出8 :: Integer。 - 适配多态展示:因为原表达式是多态的,GHCi会把具体的
8 :: Integer包装成逻辑上等价于fromInteger 8的多态值,但输出时直接显示8。这里不需要Prelude里有fromInteger x + fromInteger y = fromInteger (x + y)的显式规则,因为所有合法的Num实例都必须遵守这个类型类定律(这是Num实例的约定,不是硬编码的代码),所以不管后续适配哪个Num实例,结果都一致。
二、默认类型机制的作用分析
你发现的default ()时3 + 5能正常计算,但\(x :: Float) -> x^2过不了类型检查的现象,原因是:
3 + 5不受default ()影响:如前面所说,GHCi对无约束的Num a => a表达式有内置 fallback,就算default列表为空,也会自动选Integer实例求值,所以没问题。\(x :: Float) -> x^2的类型卡点:(^)运算符的类型是(Num a, Integral b) => a -> b -> a,其中2的类型是Integral b => b。当设置default ()时,默认类型列表为空,类型推断没法确定b的具体类型(找不到默认的Integral实例来填补),所以报错。恢复default (Integer, Double)后,Integer是Integral实例且在默认列表里,类型推断会把2推断成Integer,这样整个lambda的类型就确定为Float -> Float,自然能通过检查。
内容的提问来源于stack exchange,提问作者Evgeny Makarov
相关产品推荐
相关产品推荐

