2

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

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 函数将第一个字符串中的引号打印为字符,然后在随后的连接中正确使用它们。这种行为对我来说似乎真的很不一致。任何有助于我获得正确输出的见解将不胜感激。提前致谢!

4

2 回答 2

10

(Add e1 e2)分支show中的绑定比 更紧密(++),因此您的代码更括号内是,

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

诀窍是你真的不需要那个前导show——你直接生成字符串,只需要show递归地应用于e1and e2

show (Add e1 e2) = "( " ++ show e1 ++ " + " ++ show e2 ++ " )" 
于 2013-09-16T02:37:07.280 回答
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' 的行为在您的示例中可能看起来有点违反直觉,但实际上它的行为方式非常一致。希望知道它为什么会以这种方式运行将帮助您避免将来遇到类似的问题!

于 2013-09-16T17:46:20.283 回答