GHC因字面量类型推断错误导致类型不匹配问题求助
问题分析:GHC类型推断差异与单态限制
你的问题核心在于单态限制(Monomorphism Restriction)——这是GHC默认开启的类型推断规则,也是编译模块与GHCi表现不同的根本原因。
为什么编译时die会被推断为[Integer]?
当你在模块中定义顶层值绑定(比如die = [1..6])且未添加显式类型签名时,GHC会触发单态限制:它会将原本可推导为多态的类型强制实例化为单态类型,以此避免多态值重复计算带来的性能开销。对于数字字面量,GHC默认选择Integer作为实例化目标,因此die的类型被固定为[Integer],而非你预期的多态(Num a, Enum a) => [a]。
这直接导致后续类型不匹配:在dieRolls的列表推导中,newRoll的类型是Integer,而oldSum是dieRolls返回的Integral a => [a]中的泛型a,(+)要求两个操作数类型一致,GHC无法将刚性类型变量a统一为Integer,因此抛出类型不匹配错误。
为什么GHCi里的类型推断结果不同?
GHCi默认关闭了单态限制(通过-XNoMonomorphismRestriction选项),因此在交互式环境中定义die = [1..6]时,GHC会保留它的多态类型(Num a, Enum a) => [a],与直接查询[1..6]的类型结果一致。
关于惰性求值的疑问
这个现象和惰性求值完全无关:单态限制是类型推断阶段的规则,而惰性求值是运行时计算时机的规则,二者属于独立的语言机制,不存在违反惰性求值的情况。
解决方法
你有两种方式解决该问题:
- 添加显式多态类型签名:保留你最初写的
die :: Integral a => [a](或更通用的die :: (Num a, Enum a) => [a]),直接明确多态类型,跳过单态限制的触发条件。 - 关闭单态限制:在代码文件开头添加编译指令
{-# LANGUAGE NoMonomorphismRestriction #-},或编译时附加-XNoMonomorphismRestriction参数,让GHC对顶层值绑定保留多态类型。
内容的提问来源于stack exchange,提问作者Foobie Bletch
相关产品推荐
相关产品推荐

