Reputation: 3
This type given by the exercise is used for logical propositions.What I'm trying to do is define an instance for Show to this particular type.
This here is my code:
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
For example, the p1 defined above , after show defined is supposed to appear as : "-((-A /\ B) / C)"
I'm getting this error:
T1516.hs:48:33: error:
lexical error in string/character literal at character '"'
Upvotes: 0
Views: 1145
Reputation: 120711
The expression "/\ "
is parsed thus:
"
: a string literal starts here./
: a forward-slash character\
: the start of an escape sequence. Backslashes in string literals are not interpreted as an actual backslash character that should appear in the string you're trying to define, but as a control character introducing such an escape sequence. But then...: a space. Spaces can't be part of escape sequences, but there is one way in which this can be done nevertheless: if you're trying to escape a line break in a long string literal. for instance (line breaks highlighted)
foo :: String↲
foo = " bla bla \ ↲
\ bum blum blam \↲
\ gum gao wo"↲
is a legal string literal. The backslashes extend it into the next line, namely until the the leading backslash there, and it doesn't matter that there are spaces between the trailing backslash and the line end. What you have in your code is not ok though:
"
is illegal at this point, because you've started an escape sequence that can only be a newline, but this is not a newline.What you want instead is a literal backslash. You can achieve that in a string literal with the escape sequence \\
show (And s d) = show s ++ "/\\ " ++ show d
show (Or s d) = show s ++ "\\/" ++ show d
If you have lots of backslashes in string literals, you may consider using raw string literals which don't have any escaping.
A nicer alternative is to just use proper Unicode symbols:
show (And s d) = show s ++ "∧" ++ show d
show (Or s d) = show s ++ "∨" ++ show d
these don't need to be escaped in any way.
BTW this Show
instance won't really work properly, namely it won't have proper grouping / precedence. For instance, And (Or a b) (Or c d)
will be rendered as a∨b∧c∨d
, which is logically different. To get proper parenthisation, you need to define showsPrec
rather than the simple 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
Also note that it's considered good etiquette that Show
instances should spit out valid Haskell code. For the ∧
and ∨
operators that's easy enough to achieve:
infixr 3 ∧
(∧) = And
infixr 2 ∨
(∨) = Or
but Haskell doesn't have support for prefix operators like ¬
. You could actually get prefix -
by implementing a Num
instance, but please don't, this would be very confusing. So, you should better change the Not
clause to just yield "Not"
:
showsPrec p (Not e) = showParen (p>=10)
$ ("Not "++) . showsPrec 10 e
Upvotes: 2
Reputation: 34401
Write "\\/"
instead of "\/"
. Symbols starting with \
are called escape sequences, and there is no \/
sequence. The \\
sequence just outputs \
, which is exactly what you need.
Note that this isn't specific to Haskell language.
Upvotes: 3