练习中给出的这种类型用于逻辑命题。我想做的就是为此特定类型的Show定义一个实例。
这是我的代码:
data Prop = Var String | Not Prop | And Prop Prop | Or Prop Prop
p1::Prop
p1 = Not (Or (And (Not( Var "A")) (Var "B")) (Var "C"))
instance (Show Prop) where
Var s = show s
Not s = "-" ++ show s
And s d = show s ++ "/\ " ++ show d
Or s d = show s ++ "\/" ++ show d
例如,在show定义之后,上面定义的p1应该显示为: “-((-A / \ B)/ C)”
我收到此错误:
T1516.hs:48:33: error:
lexical error in string/character literal at character '"'
答案 0 :(得分:2)
写"\\/"
而不是"\/"
。以\
开头的符号称为转义序列,没有\/
序列。 \\
序列仅输出\
,这正是您所需要的。
请注意,这并非特定于Haskell语言。
答案 1 :(得分:2)
表达式"/\ "
的解析方式如下:
"
:字符串文字从此处开始。/
:正斜杠字符\
:escape sequence的开始。字符串文字中的反斜杠不是解释为实际的反斜杠字符,该字符应出现在您要定义的字符串中,而是解释为引入这种转义序列的控制字符。但是... :一个空格。空格不能是转义序列的一部分,但是仍然可以通过一种方法来完成:如果您要转义长字符串文字中的换行符。例如(突出显示换行符)
foo :: String↲
foo = " bla bla \ ↲
\ bum blum blam \↲
\ gum gao wo"↲
是合法的字符串文字。反斜杠将其扩展到下一行,即直到该行的前导反斜杠为止,并且在尾随的反斜杠和行尾之间没有空格也没关系。您的代码中的内容虽然不正确:
"
在这一点上是非法的,因为您已经开始了只能是换行符的转义序列,但这不是换行符。您想要的是文字反斜杠。您可以使用转义序列\\
show (And s d) = show s ++ "/\\ " ++ show d
show (Or s d) = show s ++ "\\/" ++ show d
如果字符串文字中有很多反斜杠,则可以考虑使用raw string literals,它们没有任何转义。
一个更好的选择是只使用适当的Unicode符号:
show (And s d) = show s ++ "∧" ++ show d
show (Or s d) = show s ++ "∨" ++ show d
这些都不需要以任何方式转义。
顺便说一下,这个Show
实例不能真正正常工作,即它没有适当的分组/优先级。例如,And (Or a b) (Or c d)
将呈现为a∨b∧c∨d
,这在逻辑上是不同的。要获得正确的括号,您需要定义showsPrec
而不是简单的show
:
instance (Show Prop) where
showsPrec p (Var s) = showsPrec p s
showsPrec p (Not e) = showParen (p>=7)
$ ("¬"++) . showsPrec 7 e
showsPrec p (And s d) = showParen (p>=3)
$ showsPrec 3 s ++ "∧" ++ showsPrec 3 d
showsPrec p (Or s d) = showParen (p>=2)
$ showsPrec 2 s ++ "∨" ++ showsPrec 2 d
还要注意,Show
实例应该吐出有效的Haskell代码被认为是一种良好的礼节。对于∧
和∨
运算符,很容易实现:
infixr 3 ∧
(∧) = And
infixr 2 ∨
(∨) = Or
但是Haskell不支持前缀¬
之类的前缀运算符。实际上,您可以通过实现一个-
实例来获得前缀Num
,但是请不要,这会非常令人困惑。因此,您最好将Not
子句更改为仅产生"Not"
:
showsPrec p (Not e) = showParen (p>=10)
$ ("Not "++) . showsPrec 10 e