如何显示'在Haskell中实现?

时间:2012-08-28 21:28:56

标签: haskell show typeclass

我试图理解类型系统在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行最后都应该有类型签名。

感谢所有回答的人!

3 个答案:

答案 0 :(得分:9)

这与默认(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

中描述

答案 1 :(得分:4)

由于1可以具有任何Num类型,因此编译器必须使用某种方法来选择某种类型。这是由违约处理的。但默认只发生在Prelude课程而不是你的课程。查看有关Haskell报告中的默认值的部分,并将其全部拼写出来。

答案 2 :(得分:3)

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

您自己的类型类MyShowNum没有任何关系,因此Haskell无法使用默认规则为您选择。 [抱歉,我的上一版本错误地解决了这个问题。]

这只是36.7等数字文字的一种奇怪现象,因为它们已经过载(可以代表多种类型的数据),所以你不会遇到这个问题其他类型,如Char等。