【发布时间】: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 都应该在末尾有类型签名。
感谢所有回答的人!
【问题讨论】: