【问题标题】:Int vs Integer in class instance类实例中的 Int vs Integer
【发布时间】:2010-07-25 09:32:33
【问题描述】:
class Visible a where
 toString :: a -> String
 size   :: a -> Int

intToString :: (Integral t) => t -> String
intToString 0 = "0"
intToString 1 = "1"
intToString 2 = "2"
intToString 3 = "3"
intToString 4 = "4"
intToString 5 = "5"
intToString 6 = "6"
intToString 7 = "7"
intToString 8 = "8"
intToString 9 = "9"
intToString n 
 | ((div n 10) == 0) = (intToString (mod n 10))
 | otherwise         = (intToString (div n 10)) ++ (intToString (mod n 10))

现在

instance Visible Int where
 toString = intToString
 size n   = length (toString n)

如果我输入类似 (toString 55) 之类的内容,则会在提示符处给我一个关于不明确类型变量的错误

但是

instance Visible Integer where
 toString = intToString
 size n   = length (toString n)

没有。

什么给了?

【问题讨论】:

  • 仅供参考,这是您的 intToString 的替代定义:intToString = show

标签: haskell


【解决方案1】:

这里发生了两件事。请记住,Haskell 中的数字文字是多态的。那就是:

x = 55

真正的意思

x :: Num a => a
x = fromIntegral 55

这适用于您在任何地方编写的所有数字。这可能很难处理,因此 GHCi 实现了类型默认:如果类型不明确,它假定裸数字是 IntegersDoubles

当您在 GHCi 提示符下写入 toString 55 时,GHCi 会推断数字 55 的类型为 (Visible a, Num a) => a。如果范围内只有 Visible Int,则默认类型 Integer 不起作用,因为它不' 不满足类约束(没有Visible Integer),因此 GHCi 抱怨类型变量不明确,因为它不知道要为表达式实例化哪种类型。如果您在范围内确实有 Visible Integer,则 Integer 的默认类型可以正常工作。

如果您想使用 Integer 以外的类型,可以使用 toString (55 :: Int) 中的显式类型

【讨论】:

    【解决方案2】:

    我在this link 找到了一个可能的解释。我认为文字的默认解释是 ghci 中的整数。但是如果这不起作用,ghci 就会开始对他必须对文字进行哪种解释感到困惑(Int、Double、Float ......)。 随后他给出了关于歧义的错误。命令 (toString (55:Int)) 没有给出错误,因为 GHCi 知道他必须将 55 解释为 Int

    您不是将此方法应用于特定类型的值,而是应用于 另一个重载类型的值,即您的文字 5。这 意味着 Haskell 必须弄清楚选择哪种具体类型 在这种情况下为“a”。 Haskell 的类型类是开放的,通常不会随机 如果多个可能匹配,则选择一个。在这种情况下,有一个实例 对于 Integer (在您的第一个示例中)或 Int (在您的第二个示例中),但是有 也可能是 Float 或 Double 的另一个。哪个是 正确的那一个?好吧,正如我所说,通常 Haskell 在这里是保守的 只是抱怨,因此你得到“不明确的类型变量”错误 在第二种情况下。 但是,Haskell 中有一种机制可以提供启发式方法,并且 这就是“违约”的全部意义所在。在正常情况下, Haskell 对于数字类型,在有歧义的情况下会选择“整数”, 如果这不起作用,它会尝试“Double”。它不会尝试“Int” 尽管。这解释了为什么您的第一个示例(偶然)有效。 如果您向 GHCi 询问类型,则不应用默认值,但您 可以观察到它在很多地方发生。例如,

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 1970-01-01
      • 2011-08-17
      • 1970-01-01
      • 2012-10-02
      相关资源
      最近更新 更多