Haskell中为什么Num类型类实例可被当作Floating类型使用?
问题解答
核心的误解在于你对fromIntegral返回值约束的理解:Num b => b的含义是「返回值可以是任意实现了Num类型类的类型」,而不是「返回值是通用的Num类型、只能使用Num定义的操作」。
我们可以顺着函数组合的类型推导逻辑一步步看:
- 第一步,
fromIntegral接收输入的Integral类型值,返回值需要同时满足两个约束:- 满足
fromIntegral本身要求的Num约束 - 满足后续
sqrt要求的Floating约束
由于所有Floating类型类的实现天然都实现了Num(Floating继承自Fractional,而Fractional继承自Num),这个合并约束完全合法,编译器会自动推导选择同时满足两个约束的具体类型,默认会选用Double。
- 满足
- 第二步,
sqrt接收上述推导得到的Floating类型值,返回同类型的结果,而Double这类标准Floating实现同时也实现了RealFrac类型类,刚好满足floor的入参要求。 - 第三步,
floor接收RealFrac类型值,返回Integral类型的结果,刚好匹配isqrt的返回值约束。
我们可以用具体值举例验证流程:
输入为Int类型的4时:
fromIntegral 4被推导为Double类型的4.0sqrt 4.0返回Double类型的2.0floor 2.0返回Int类型的2,完全符合预期。
补充:Haskell不存在面向对象语言里「父类隐式转换为子类」的操作,这里的所有类型匹配都是编译期通过多态类型推导完成的,编译器会自动找到同时满足所有链路约束的具体类型,只要该类型存在,代码就能编译通过。
内容的提问来源于stack exchange,提问作者Red_Black
相关产品推荐
相关产品推荐

