【问题标题】:how is 'show' implemented in Haskell?Haskell 中的“show”是如何实现的?
【发布时间】:2012-08-28 21:28:56
【问题描述】:

我试图了解类型系统在 Haskell 中是如何工作的。

class (Show a) => MyShow a where 
    myShow :: a -> String

instance MyShow Integer where 
    myShow = show 

myshow :: (Show a) => a -> String
myshow = show

main  = do 
    putStrLn $ myshow 1
    putStrLn $ myShow (2 :: Integer) -- why do I need '::Integer' here?

为什么 'myshow 1' 在没有类型的情况下工作,而 'myShow 2' 在没有明确类型的情况下会导致错误:

Ambiguous type variable `a0' in the constraints:
  (MyShow a0) arising from a use of `myShow'
              at nooverinst.hs:12:16-21
  (Num a0) arising from the literal `2' at nooverinst.hs:12:23
Probable fix: add a type signature that fixes these type variable(s)
In the second argument of `($)', namely `myShow 2'
In the expression: putStrLn $ myShow 2
In the expression:
  do { putStrLn $ myshow 1;
       putStrLn $ myShow 2 }

同样奇怪的是,使用GHCI的时候竟然没有报错:

*Main> myShow 2
"2"

那么,在这种情况下,“myshow”和“myShow”有什么区别?它们都被定义为与“show”相同。我错过了什么?

更新:

答案总结: 这种行为与违约有关。 'show 1' 和 'myshow 1' 工作的事实是一个特例(见Haskell report section on defaulting)。在源代码顶部添加“default ()”会关闭默认设置并导致代码在“myshow 1”处中断,因为不再通过默认设置来解决类型歧义。所以,事实上,两行 putStrLn 都应该在末尾有类型签名。

感谢所有回答的人!

【问题讨论】:

    标签: haskell show typeclass


    【解决方案1】:

    这与默认设置有关(Haskell 标准中较暗的角落之一),如 http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-790004.3.4 所述

    简而言之,Haskell 以一种特殊的方式处理数值类,并且默认数值类会自动产生歧义,但仅涉及的其他约束是基类。从这个意义上说,Show 也很特别,而您定义自己的 MyShow 则以不同的方式处理。

    在 GHCi 中,扩展的默认规则开始生效,稍微放宽了限制。这些描述在http://www.haskell.org/ghc/docs/latest/html/users_guide/interactive-evaluation.html#extended-default-rules

    【讨论】:

      【解决方案2】:

      由于 1 可以具有任何 Num 类型,因此编译器必须使用某种方法来选择某种类型。这是由默认值处理的。但是默认只发生在 Prelude 类而不是你的类。查看 Haskell 报告中有关违约的部分,所有内容都已详细说明。

      【讨论】:

        【解决方案3】:

        有几种数字类型(Num 的实例),当您编写 2 时,Haskell 不知道您指的是哪一种。 通常你可以侥幸逃脱,因为 ghc/ghci 被编程为像 2+2 这样的表达式选择像 Integer 这样的默认类型。 你在 myshow 中侥幸逃脱,因为 Haskell 正在使用与它自动选择的 Num 实例相关联的 Show 实例,而不是在 myShow 中。

        你自己的 typeclass MyShow 和 Num 没有任何关系,所以 Haskell 不能使用默认规则为你选择。 [对不起,我以前的版本弄错了。]

        这只是像3、6.7 等数字文字的奇怪之处,因为它们被重载(可以表示不止一种类型的数据),所以你不会遇到像 @ 这样的其他类型的问题987654333@等

        【讨论】:

        • 嗯...为许多类型定义了“show”这一事实应该使选择正确的类型变得更加困难(即 GHC 应该在编译时抱怨“myshow 1”)。 GHCI 旁白,为什么缺少类型会导致编译错误?
        • 默认规则处理myshow 1,但不处理您自己的myShow。 Ghc/ghci 必须知道一切是什么类型,因为您可以根据参数的类型编写具有不同定义的函数,并且它需要知道使用哪个类型。它通常可以为您解决问题,但在这种情况下,它不知道您是指 Int 还是 Integer 还是类型类 Integral 中的其他内容。 (2 是 fromInteger 2 的缩写 - 请参阅 hackage.haskell.org/packages/archive/base/latest/doc/html/…)
        猜你喜欢
        • 1970-01-01
        • 2021-05-04
        • 2011-02-10
        • 2012-01-18
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 2010-09-19
        相关资源
        最近更新 更多