使用uncurry函数的特定类型推断

Ces*_*ata 6 haskell types ghc monomorphism-restriction

我一直在玩uncurryGHCi 的功能,我发现了一些我根本无法得到的东西.当我申请uncurry(+)功能,并结合该像在下面的代码中的一些变量,所述编译器推断它的类型是特定于Integer:

Prelude> let add = uncurry (+)
Prelude> :t add
add :: (Integer, Integer) -> Integer
Run Code Online (Sandbox Code Playgroud)

但是,当询问以下表达式的类型时,我得到(我期望的)正确的结果:

Prelude> :t uncurry (+)
uncurry (+) :: (Num a) => (a, a) -> a
Run Code Online (Sandbox Code Playgroud)

会导致什么?这是GHCi特有的吗?

这同样适用于let add' = (+).

注意:我无法使用编译文件重现它.

luq*_*qui 21

这与ghci无关.这是单形态限制令人恼火.如果您尝试编译以下文件:

add = uncurry (+)
main = do
    print $ add (1,2 :: Int)
    print $ add (1,2 :: Double)
Run Code Online (Sandbox Code Playgroud)

你会收到一个错误.如果你扩展:

main = do
    print $ uncurry (+) (1,2 :: Int)
    print $ uncurry (+) (1,2 :: Double)
Run Code Online (Sandbox Code Playgroud)

正如所料,一切都很好.单态限制拒绝制作"看起来像一个值"的东西(即在equals的左侧没有参数定义)类型多态,因为这会破坏通常会发生的缓存.例如.

foo :: Integer
foo = expensive computation

bar :: (Num a) => a
bar = expensive computation
Run Code Online (Sandbox Code Playgroud)

foo保证只计算一次(好吧,至少在GHC中),而bar每次提到时都要计算.单态约束试图通过默认为前者来拯救你从后者看起来像你想要的那样.

如果您仅使用该函数一次(或始终使用相同类型),则类型推断将负责为您推断正确的类型.在那种情况下,ghci通过更快的猜测做了一些稍微不同的事情.但是在两种不同的类型中使用它会显示正在发生的事情.

如有疑问,请使用类型签名(或关闭可怜的东西{-# LANGUAGE NoMonomorphismRestriction #-}).