这篇文章是由解决类型为`f = f (<*>) pure`所引发的,其中讨论了一个更复杂的例子,但这个例子也可以使用。
以下定义可以无问题编译:
当然,这在运行时是不起作用的,但这并非问题所在。重点是`w`本身的定义使用了
然而,如果我们删除签名,则GHC推断出的不是上述类型,而只有具体类型:
尽管
然而,在
为了排除这与默认值有关的可能性:
为什么多态类型无法推断?
以下定义可以无问题编译:
w :: Integral a => a
w = fromInteger w
当然,这在运行时是不起作用的,但这并非问题所在。重点是`w`本身的定义使用了
w :: Integer
的一个特殊版本。显然,这是一个合适的实例化,因此可以通过类型检查。然而,如果我们删除签名,则GHC推断出的不是上述类型,而只有具体类型:
w' = fromInteger w'
GHCi> :t w
w :: Integral a => a
GHCi> :t w'
w' :: Integer
当我看到这个时,我相当确定这是单态限制在起作用。众所周知,例如
i = 3
GHCi> :t i
i :: Integer
尽管
i :: Num p => p
是完全可行的。实际上,如果启用了-XNoMonomorphismRestriction
,即禁用了单态限制,则会推断出i :: Num p => p
。然而,在
w'
的情况下,即使禁用了单态限制,仅推断出Integer
类型。为了排除这与默认值有关的可能性:
fromFloat :: RealFrac a => Float -> a
q :: RealFrac a => a
q = fromFloat q
q' = fromFloat q'
GHCi> :t q
q :: RealFrac a => a
GHCi> :t q'
q' :: Float
为什么多态类型无法推断?
w' = fromInteger w'
是递归的,因此不是简单的)? - AlecfromInteger
的类型为(Num a) => Integer -> a
,而且由于w'
被用作fromInteger
的输入,这难道不意味着Integer
是它唯一可能的类型吗?事实上,我对具有多态类型签名版本的编译结果感到非常惊讶。(所以正如我所说,可能漏掉了什么。) - Robin ZigmondInteger
显然是w'
的唯一可能的 单态 类型,但是正如w
所展示的那样,多态类型也完全可以。毕竟,多态类型可以被实例化为单态类型,只要它满足约束条件即可。 - leftaroundabout