【问题标题】:Specific type inference using uncurry function使用 uncurry 函数的特定类型推断
【发布时间】:2011-06-27 07:23:30
【问题描述】:

我一直在使用 GHCi 中的 uncurry 函数,我发现了一些我根本无法理解的东西。当我将uncurry 应用于(+) 函数并将其绑定到如下代码中的某个变量时,编译器会推断其类型特定于Integer

Prelude> let add = uncurry (+)
Prelude> :t add
add :: (Integer, Integer) -> Integer

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

Prelude> :t uncurry (+)
uncurry (+) :: (Num a) => (a, a) -> a

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

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

注意:我无法使用已编译的文件重现该内容

【问题讨论】:

标签: haskell types ghc monomorphism-restriction


【解决方案1】:

这与 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 #-} 关闭这个可怜的东西)。

【讨论】:

    【解决方案2】:

    使用 ghci 扩展默认规则具有魔力。基本上,除其他外,Num 约束默认为 Integer,Floating 约束默认为 Double,否则会出现错误(在这种情况下,由于邪恶的单态性限制)。

    【讨论】:

    • 确实,这是另一件重要的事情。
    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 2021-03-09
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    相关资源
    最近更新 更多