#1. The decision about dropping the parentheses depends on which side of the operator we're on. So, here's the new prettyShow -- changes in bold:
prettyShow :: (Show a, Num a) => SymbolicManip a -> String
-- Show a number or symbol as a bare number or serial
prettyShow (Number x) = show x
prettyShow (Symbol x) = x
prettyShow (BinaryArith op a b) =
let pa = maybeLeftParen a op
pb = maybeRightParen b op
pop = op2str op
in pa ++ pop ++ pb
prettyShow (UnaryArith opstr a) =
opstr ++ "(" ++ show a ++ ")"
Now, for the helper functions. Let's start with handling the left-paren:
maybeLeftParen :: (Show a, Num a) => SymbolicManip a -> Op -> String
maybeLeftParen x@(BinaryArith op1 _ _) op
| op1 == op && isRightAssociative op = "(" ++ prettyShow x ++ ")"
| (opPrio op1) < (opPrio op) = "(" ++ prettyShow x ++ ")"
| otherwise = prettyShow x
maybeLeftParen x _ = simpleParen x
For this to work, we need to know each operator's priority, and whether the operator is right-associative. These are trivial (the priorities are taken from Haskell's definitions; type :i (+) in ghci, for example):
opPrio :: Op -> Int opPrio Plus = 6 opPrio Minus = 6 opPrio Mul = 7 opPrio Div = 7 opPrio Pow = 8 isRightAssociative :: Op -> Bool isRightAssociatove Pow = True isRightAssociative _ = False
Finally, for handling parenthesis to the right of the operator, we have this:
maybeRightParen :: (Show a, Num a) => SymbolicManip a -> Op -> String
maybeRightParen x@(BinaryArith op1 _ _) op
| prio1 < prio = "(" ++ prettyShow x ++ ")"
| prio1 == prio && opIsMinusOrDiv = "(" ++ prettyShow x ++ ")"
| otherwise = prettyShow x
where prio1 = opPrio op1
prio = opPrio op
opIsMinusOrDiv = (op == Minus) || (op == Div)
maybeRightParen x _ = simpleParen x
0 comments:
Post a Comment