自定义数据类型的Haskell show定义对前导引号的使用不一致

时间:2013-09-16 02:31:07

标签: haskell show

这是我正在处理的代码的简化版本

data ArithExp = Con Int
          | Add ArithExp ArithExp

instance Show ArithExp where
          show (Con i)     = show i
          show (Add e1 e2) = show "( " ++ show e1 ++ " + " ++ show e2 ++ " )"

所以,如果我运行命令

Add (Con 6) (Con 0)

我想要的输出是:

( 6 + 0 )

但上面的代码打印出来:

"( "6 + 0 )

据我所知,show函数将第一个字符串中的引号打印为字符,然后在后面的串联中正确使用它们。这种行为对我来说似乎很不一致。任何有助于我获得正确输出的见解都将非常感激。 提前谢谢!

2 个答案:

答案 0 :(得分:10)

(Add e1 e2)分支show中绑定比(++)更紧密,因此您的代码更为合理,

show (Add e1 e2) = (show "( ") ++ (show e1) ++ " + " ++ (show e2) ++ " )"

诀窍在于你并不真正需要领先show ---你直接生成字符串,只需要show递归地应用于e1和{{1 }}

e2

答案 1 :(得分:0)

通常,show会尝试打印您的数据,如果您要将其键入ghci,它将评估为等效的数据值。想想在字符串的情况下这意味着什么。如何键入字符串值,以便Haskell将其解释为字符串而不是要评估的表达式?

这是一个示例ghci会话,说明我的意思:

> let myString = "Hello"
> putStrLn $ show myString
=> "Hello"
> :t "Hello"
=> "Hello" :: String
> putStrLn myString
=> Hello
> :t Hello
=> Not in scope: data constructor 'Hello'

由于您最初必须在引号中键入字符串,以便它将计算为字符串而不是构造函数表达式,show将在其周围加上引号,以便您可以将值粘贴回ghci并获取字符串值而不是构造函数值。

虽然show的行为在您的示例中可能看起来有点违反直觉,但实际上它的行为方式却非常一致。希望知道它为什么这样做会帮助你避免将来遇到这样的问题!