{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-} module Data.Logic.Classes.Pretty ( Pretty(pretty) , HasFixity(fixity) , TH.Fixity(..) , TH.FixityDirection(..) , topFixity , botFixity ) where import qualified Language.Haskell.TH.Syntax as TH import Text.PrettyPrint (Doc, text) -- | The intent of this class is to be similar to Show, but only one -- way, with no corresponding Read class. It doesn't really belong -- here in logic-classes. To put something in a pretty printing class -- implies that there is only one way to pretty print it, which is not -- an assumption made by Text.PrettyPrint. But in practice this is -- often good enough. class Pretty x where pretty :: x -> Doc -- | A class used to do proper parenthesization of formulas. If we -- nest a higher precedence formula inside a lower one parentheses can -- be omitted. Because @|@ has lower precedence than @&@, the formula -- @a | (b & c)@ appears as @a | b & c@, while @(a | b) & c@ appears -- unchanged. (Name Precedence chosen because Fixity was taken.) -- -- The second field of Fixity is the FixityDirection, which can be -- left, right, or non. A left associative operator like @/@ is -- grouped left to right, so parenthese can be omitted from @(a / b) / -- c@ but not from @a / (b / c)@. It is a syntax error to omit -- parentheses when formatting a non-associative operator. -- -- The Haskell FixityDirection type is concerned with how to interpret -- a formula formatted in a certain way, but here we are concerned -- with how to format a formula given its interpretation. As such, -- one case the Haskell type does not capture is whether the operator -- follows the associative law, so we can omit parentheses in an -- expression such as @a & b & c@. class HasFixity x where fixity :: x -> TH.Fixity -- Definitions from template-haskell: -- data Fixity = Fixity Int FixityDirection -- data FixityDirection = InfixL | InfixR | InfixN -- | This is used as the initial value for the parent fixity. topFixity :: TH.Fixity topFixity = TH.Fixity 0 TH.InfixN -- | This is used as the fixity for things that never need -- parenthesization, such as function application. botFixity :: TH.Fixity botFixity = TH.Fixity 10 TH.InfixN instance Pretty String where pretty = text