[英]how is 'show' implemented in Haskell?
我试图了解类型系统在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报告部分 )。 在源代码之上添加'default()'会关闭默认值并导致代码在'myshow 1'处中断,因为类型歧义不再通过默认来解决。 所以,实际上,两个putStrLn行都应该在最后有类型签名。
感谢所有回答的人!
这与默认(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可以具有任何Num类型,因此编译器必须使用某种方法来选择某种类型。 这是由违约处理的。 但默认只发生在Prelude课程而不是你的课程。 查看有关Haskell报告中的默认值的部分,并将其全部拼写出来。
有几种数字类型( Num
实例),Haskell在你写2
时不知道你的意思。 通常你可以逃脱它,因为ghc / ghci被编程为像2+2
这样的表达式选择像Integer这样的默认类型。 你在myshow
中myshow
因为Haskell正在使用与自动选择的Num
实例绑定的Show
实例,但不是在myShow
。
你自己的类型类MyShow
与Num
没有任何关系,所以Haskell不能使用默认规则为你选择。 [抱歉,我的上一版本错误地解决了这个问题。]
这仅仅是数字文字像一个古怪3
, 6.7
等,因为它们是重载(可以代表一个以上类型的数据),这样你就不会遇到这个问题与其他类型如Char
等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.