我一直在玩uncurry
在 GHCi 中运行函数,我发现了一些我根本无法理解的东西。当我申请时uncurry
to the (+)
函数并将其绑定到某个变量,如下面的代码所示,编译器推断其类型特定于Integer
:
Prelude> let add = uncurry (+)
Prelude> :t add
add :: (Integer, Integer) -> Integer
但是,当询问以下表达式的类型时,我得到(我期望的)正确的结果:
Prelude> :t uncurry (+)
uncurry (+) :: (Num a) => (a, a) -> a
什么会导致这样的情况呢? GHCi 特有吗?
这同样适用于let add' = (+)
.
注意:我无法使用编译文件重现该内容.
这与ghci无关。这是令人恼火的单态限制。如果您尝试编译以下文件:
add = uncurry (+)
main = do
print $ add (1,2 :: Int)
print $ add (1,2 :: Double)
你会得到一个错误。如果你展开:
main = do
print $ uncurry (+) (1,2 :: Int)
print $ uncurry (+) (1,2 :: Double)
一切都很好,正如预期的那样。单态性限制拒绝使“看起来像一个值”的东西(即在等号的左侧没有参数定义)类型类多态,因为这会破坏通常发生的缓存。例如。
foo :: Integer
foo = expensive computation
bar :: (Num a) => a
bar = expensive computation
foo
保证只计算一次(好吧,至少在 GHC 中),而bar
每次提及时都会进行计算。单态性限制旨在通过默认为前一种情况来将您从后一种情况中拯救出来,而这正是您想要的。
如果您只使用该函数一次(或始终使用同一类型),类型推断将负责为您推断正确的类型。在这种情况下,ghci 会通过更快地猜测来做一些稍微不同的事情。但在两种不同类型中使用它可以显示发生了什么。
如有疑问,请使用类型签名(或使用以下命令关闭该讨厌的东西){-# LANGUAGE NoMonomorphismRestriction #-}
).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)