data Expr = Var Char | Not Expr | And Expr Expr | Or Expr Expr deriving (Eq, Ord)
instance Show Expr where
show (Var x) = [x]
show (Not (Var y)) = "~" show (Var y)
show (And (Var x) (Var y)) = show (Var x) " ^ " show (Var y)
show ((Or (Var x) (Var y))) = show (Var x) " v " show (Var y)
show (Not (Or (Var x) (Var y))) = "~(" show (Or (Var x) (Var y)) ")"
show (And (Var x) (And (Var y) (Var z))) = show (Var x) " ^ " "(" show (And (Var y) (Var z)) ")"
I`m not sure exactly why i get this error when i run:
>(Not (Not (Var 'a')))
*** Exception: (21,5)-(26,112): Non-exhaustive patterns in function show
Can anyone help me.
CodePudding user response:
An And
can also contain another And
, so for example And (And (Var 'x') (Var 'y')) (Var 'z')
. In your Show
instance you always assume that the parameters are Var
s, that is not necessary.
You can implement the Show
instance as:
instance Show Expr where
show (Var x) = [x]
show (Not x) = "~ (" show x ")"
show (And x y) = "(" show x " ^ " show y ")"
show (Or x y) = "(" show x " v " show y ")"
This will introduce a lot of parenthesis. Therefore it is better to work with a precedence parameter. In fact the Show
instance already has support for this: you can work with showsPrec :: Int -> a -> String -> String
. Here the Int
parameter is the operator precedence of the outer context, and the first String
parameter is the string that needs to be appended at the end: that is done for performance reasons.
We thus can implement this as:
instance Show Expr where
showsPrec n (Var x) = (x :)
showsPrec n (Not x) = showParen (n > 9) ( ('~' :) . showsPrec 10 x)
showsPrec n (And x y) = showParen (n > 8) ((showsPrec 9 x) . (" ^ " ) . showsPrec 9 y)
showsPrec n (Or x y) = showParen (n > 7) ((showsPrec 8 x) . (" v " ) . showsPrec 8 y)
Here we will show parenthesis for not
if the outer countext has a precedence higher than 9
, and call the showPrec
with a precence 10 such that the showPrec
inside will not print extra parenthesis, unless it has a precedence of 10 or higher. The same applies for the other functions.
This thus means that we can print an expression with parenthesis like:
ghci> show (Not (And (Or (Not (Var 'x')) (Var 'y')) (Var 'z')))
"~((~x v y) ^ z)"
Here the And … …
will thus print parenthesis since it is called with a precedence of nine, and the threshold is 8 to print parenthesis. But there are no brackets for around ~x
, since the threshold is lower than 10.
CodePudding user response:
Instead of hard-coding lots of deep expressions, you should just pattern match on the topmost constructors and then recurse down.
instance Show Expr where
show (Var v) = [v]
show (Not x) = "Not (" show x ")"
show (And x y) = "(" show x ") ∧ (" ...
show (Or x y) = ...
Remember to implement the ∧
and ∨
operators if you mention them in the show
results.
infixr 3 ∧
(∧) :: Expr -> Expr -> Expr
(∧) = And
Actually it is preferred to not implement show
when defining recursive-data Show
instances, instead implement showsPrec
which has a more sophisticated way of adding parentheses as needed.