为何mth4在文件与GHCi交互环境中定义时类型不同?
为何函数
mth4在文件中定义与直接在GHCi交互环境中定义时类型不同? 问题重现
文件定义(test2.hs)
mth1 x y z = x * y * z mth2 x y = \z -> x * y * z mth3 x = \y -> \z -> x * y * z mth4 = \x -> \y -> \z -> x * y * z
加载到GHCi后,mth4的类型为:
mth4 :: Integer -> Integer -> Integer -> Integer
GHCi直接定义
在GHCi中直接输入定义后,mth4的类型为:
mth4 :: Num a => a -> a -> a -> a
原因分析
这是**Haskell单态限制(Monomorphism Restriction)**的行为差异导致的:
- 文件编译/加载场景:默认启用单态限制。该规则针对无显式类型签名的顶级绑定(如
mth4这种不带参数的定义),会将其推断为单态类型(而非多态)。GHC会选择Integer作为Num类型类的默认实例,因此mth4被推断为Integer专用的函数。而mth1/mth2/mth3因为带有显式参数,属于函数绑定,单态限制对其不生效,所以保留多态类型。 - GHCi交互场景:默认关闭单态限制(启用
NoMonomorphismRestriction扩展)。此时所有无显式类型签名的绑定都会被推断为多态类型,因此mth4的类型保留了Num a =>的多态约束。
验证与解决方法
- 让文件中的
mth4变为多态:在文件开头添加扩展声明,关闭单态限制:
重新加载后,{-# LANGUAGE NoMonomorphismRestriction #-} mth1 x y z = x * y * z mth2 x y = \z -> x * y * z mth3 x = \y -> \z -> x * y * z mth4 = \x -> \y -> \z -> x * y * zmth4的类型会变为Num a => a -> a -> a -> a。 - 显式指定类型签名:给
mth4添加多态类型签名,强制保留多态性:mth4 :: Num a => a -> a -> a -> a mth4 = \x -> \y -> \z -> x * y * z
内容的提问来源于stack exchange,提问作者peti
相关产品推荐
相关产品推荐

