【问题标题】:ghci - defaulting confusionghci - 默认混淆
【发布时间】:2017-07-03 04:16:36
【问题描述】:

在检查不同整数类型的大小(minBound,maxBound)和“十进制表示的长度”时,我碰巧看到了一些奇怪的行为。

使用 GHCi:

Prelude> :{
Prelude| let mi = minBound
Prelude|     ma = maxBound
Prelude|     le = fromIntegral $ length $ show ma
Prelude|  in [mi,ma,le] :: [Int]
Prelude| :}
[-9223372036854775808,922372036854775807,2]
                                         ^

我最期待的是19

我的第一个猜测是 maxBound 默认为 () 并因此产生 2,但我不明白这是因为 ma 应该是 Int 通过显式类型注释 (:: [Int]) - 并且通过引用透明性,所有名为 ma 的符号应该是相等的。

如果我将上面的语句放在一个文件中并将其加载到 GHCi 中,我会得到正确的结果。

那么为什么我会得到错误的结果?

【问题讨论】:

  • 我认为你的第一个猜测非常接近,ma 的类型直到后来才固定为Int,所以le 使用ma :: Bounded a => a,默认为()演出。如果你用ma = maxBound :: Int 再做一次,它应该给你 19。
  • 类型不固定怎么办?
  • 当您期望相反的行为时,任何行为都可能令人困惑。

标签: haskell types ghci monomorphism-restriction


【解决方案1】:

令人困惑的是,这仍然是单态性限制(或者更确切地说,在 GHCi 中缺乏单态性限制)。由于 GHCi 没有启用单态限制,因此您对 mima 的定义不会像您认为的那样专门化为 Int - 相反,它们保持通用 mi, ma :: Bounded a => aa 变量被实例化两次

  • 曾在fromIntegral $ length $ show ma 中作为()(如您所见,这是默认设置)
  • 曾在[mi,ma,le] :: [Int] 中作为Int

如果您希望 mima 实际上是 Int 类型,请直接注释它们

Prelude> :{
Prelude| let mi, ma :: Int
Prelude|     mi = minBound
Prelude|     ma = maxBound
Prelude|     le = fromIntegral $ length $ show ma
Prelude|  in [mi,ma,le]
Prelude| :}
[-9223372036854775808,9223372036854775807,19]

或者在 GHCi 中手动开启单态限制

Prelude> :set -XMonomorphismRestriction
Prelude> :{
Prelude| let mi = minBound
Prelude|     ma = maxBound
Prelude|     le = fromIntegral $ length $ show ma
Prelude| in [mi,ma,le] :: [Int]
Prelude| :}
[-9223372036854775808,9223372036854775807,19]

【讨论】:

  • 我认为这可能是由于MonomorphismRestriction 但我尝试-XNoMono... - 这已经是 GHCi 中的默认设置,并且再次得到不正确的结果
  • @epsilonhalbe 这是我在 SO 上回答的唯一问题之一,有人真正想要MonomorphismRestriction(而不是相反)。 :)
  • 可能值得一提的是为什么单态限制通常是一个好主意-除非您提供更通用的签名或明确具有函数(即左侧有参数=),您可能不会期望您的 let 绑定是多态的。在这种情况下,您不会因此认为 mima 是多态的。
  • MonoLocalBinds 也可以避免这种混淆,这会阻止let-泛化。针对同一问题的两种不同的反混淆解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多