Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic parentheses in `Show` instances

Tags:

haskell

ghci> show (Left 3)
"Left 3"
ghci> show (Just 0)
"Just 0"
ghci> show (Just (Left 3))
"Just (Left 3)"

How does Haskell automatically put parentheses around nested constructor arguments?

like image 319
ThePiercingPrince Avatar asked Feb 13 '23 18:02

ThePiercingPrince


1 Answers

showsPrec :: Int -> a -> ShowS is the function used internally by show to consistently put parentheses around a term.

The Int parameter indicate the precedence of the outer context. If the precedence of the current constructor is greater than the precedence of the context, showParen :: Bool -> ShowS -> ShowS puts parentheses around the constructor. Here an example for a very basic AST :

data Exp = Exp :+: Exp
         | Exp :*: Exp

-- The precedence of operators in haskell should match with the AST shown
infixl 6 :+: 
infixl 7 :*:


mul_prec, add_prec :: Int
mul_prec = 7
add_prec = 6

instance Show Exp where
  showsPrec p (x :+: y) = showParen (p > add_prec) $ showsPrec (add_prec+1) x
                                                   . showString " :+: "
                                                   . showsPrec (add_prec+1) y
  showsPrec p (x :*: y) = showParen (p > mul_prec) $ showsPrec (mul_prec+1) x
                                                   . showString " :*: "
                                                   . showsPrec (mul_prec+1) y
  show t = showsPrec 0 t "" -- Default definition

showsPrec, showString, showParen, etc, act on difference lists (ShowS = String -> String), where the argument is a string appended to the result. Concatenation is done by composition, and conversion to String by application with an empty string. The show implementation use showsPrec with the lowest precedence, the expression to print, and finally, the end of the string [].

like image 73
Piezoid Avatar answered Feb 22 '23 22:02

Piezoid