为什么我被迫在这里指定一个类型?

时间:2016-09-05 23:56:16

标签: haskell typeclass

我有以下代码:

class ToString a where
    toString :: a -> String

instance ToString String where
    toString a = a

instance ToString Char where
    toString a = [a]

instance ToString Int where
    toString a = show a

instance ToString Integer where
    toString a = show a

instance ToString Float where
    toString a = show a

instance ToString Double where
    toString a = show a

我可以toString "Text"toString 't'进行编译。但如果我toString 5我得到并且错误。我被迫做toString (5::Int)

show不需要指定的类型。当我看到Show的实现时,我看不到任何神奇的东西:

instance Show Int where ...

instance Show Integer where ...

我做错了什么,需要我指定类型以及如何解决?

更新

我按照以下建议添加了{-# LANGUAGE ExtendedDefaultRules #-},并且效果很好。解决了我的问题。

2 个答案:

答案 0 :(得分:7)

您需要指定一个类型,因为5在Haskell中是多态的:

λ> :type 5
5 :: Num a => a

因此编译器不知道选择哪个Num实例。但是,由于extended defaulting,此 在ghci中工作:

λ> toString 5
"5"

答案 1 :(得分:6)

当您编写toString "Text"toString 't'时,Haskell能够确切地确定具体类型"Text"'t'[Char](又名{{1}分别是}和String。因此,它可以选择一个实例并运行您的代码。

Char略有不同。像toString 5这样的数字文字在Haskell中被重载,因此5可以是5Int,或与Double实例完全不同的东西没有Num个实例。因此,我们没有指定我们应该使用哪个ToString实例(请注意,根据您选择ToString还是Int,您将获得与现有实例不同的可观察行为。 Haskell对这种情况的一般反应是报告一个模糊的类型错误,要求你做一些事情来确定更多的类型。

Haskell规范的作者认为这对于特别是数字类型来说是一个非常常见且烦人的问题,所以他们在一定的条件下建立了默认模糊类型的机制保守地设计用于帮助仅使用标准Haskell功能的数字文字。 1

只有两种情况都会默认类型:

  1. 它的所有约束只涉及内置类型类
  2. 至少有一个类是数字(DoubleNum等)
  3. 所以Floating有效,因为show 5类型的约束是5; (Num a, Show a)是一个数字类,所有约束都是内置类。

    Num似乎应该基本相同,但是你得到约束toString 5,并且由于(Num a, ToString a)不是内置类,默认不适用,离开你有一个模糊的类型错误。

    GHCi中使用的扩展默认规则(或者如果使用ToString扩展名)放宽了“仅内置类”规则(以及其他扩展名),这使得ExtendedDefaultRules符合默认条件后的默认值所有

    GHC用户手册讨论了如何在GHCi(或(Num a, ToString a)的扩展名)中扩展通常的类型默认规则,并将它们与标准规则进行比较:

    https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#type-defaulting-in-ghci

    1 在实践中,我发现它在实际开发中是一个非常罕见的问题(我通常用一个警告类型默认的标志进行编译),但这是因为我采用了(常见的)实践为几乎所有顶级函数提供类型签名。当调用GHC来编译使用该实践编写的整个模块时,几乎总是有足够的信息可用于指定所有类型,并且永远不需要默认。

    例如,如果ExtendedDefaultRule发生在toString x是类型为x的参数的函数中,则Int完全没问题。如果x是没有显式类型的局部变量,那么它甚至会很好,但它也被传递给需要Int参数的函数。或者被列入列表以及其他已知为Int的内容。等等。

    但是在GHCi中,您提供的表达式可以一次一个地进行分析,并且通常不会打扰类型签名等可选项。在这些条件下,数字文字(和其他表达式)被更加模糊地键入更多,这是GHCi扩展默认规则的动机。