I have a simple arithmetic expression data structure that I want to be able to print. For sake of simplicity here I have made an example with 3 binary operations, addition, multiplication and division. The definition looks like this:
module ExprPrint where
import Text.Printf
data Expr = Lit Int
| Add Expr Expr
| Mul Expr Expr
| Div Expr Expr
instance Show Expr where
show (Lit x) = show x
show (Add e1 e2) = printf "(%s) + (%s)" (show e1) (show e2)
show (Mul e1 e2) = printf "(%s) * (%s)" (show e1) (show e2)
show (Div e1 e2) = printf "(%s) / (%s)" (show e1) (show e2)
The goal I have is to print the data structure while removing all superfluous parenthesis. of course the naive show function I have implemented above includes way too many of them. So what I want to do is make the Show
instance take the precedence (Div
and Mul
over Add
) and associativity(Add
and Mul
are associative while Div
is left-associative) of the operations into account.
Here are some examples:
one = Lit 1
-- Shows "((1) + (1)) + (1)" but should be 1 + 1 + 1
addAssoc = show $ Add (Add one one) one
-- Shows "((1) * (1)) * (1)" but should be 1 * 1 * 1
mulAssoc = show $ Mul (Mul one one) one
-- Shows "((1) / (1)) / (1)" but should be 1 / 1 / 1
divAssoc = show $ Div (Div one one) one
-- Shows "(1) / ((1) / (1)) but should be 1 / (1 / 1)
divAssoc2 = show $ Div one (Div one one)
-- Show "((1) * (1)) + (1)" but should 1 * 1 + 1
addPrec = show $ Add (Mul one one) one
-- Show "(1) + ((1) * (1))" but should show 1 + (1 * 1)
addPrec2 = show $ Add one (Mul one one)
Is there an "easy" to take that into account in the show instance? I think I could do it by taking all the cases into account but that would be an explosion of functions. Is there some algorithm or known way to handle this?
I hope somebody has some pointers!
Thanks.