2017-09-11 8 views
2

J'ai un type pour représenter les types de haskell:Haskell: infix d'impression Jolie et le préfixe

data Type 
    = TApp Type Type 
    | TVar Name 
    | TLit Name 
infixl 8 `TApp` 

-- a -> b 
aToB = TLit "Fun" `TApp` TVar "a" `TApp` TVar "b" 

-- Maybe (IO Int) 
maybeIOInt = TLit "Maybe" `TApp` (TLit "IO" `TApp` TLit "Int") 

Je veux imprimer comme haskell fait, à savoir littéraux qui sont des symboles sont imprimés infix tandis que d'autres préfixes sont littérale . également entre parenthèses devraient être ajoutés si nécessaire:

show aToB = "a -> b" 
show maybeIOInt = "Maybe (IO Int)" 

show ast = ??? 

Comment puis-je mettre en œuvre ce?

+1

Si vous êtes en train de faire cela pour votre propre gouverne, je comprends, sinon je vous indiquer le [haskell-src-exts] (https://hackage.haskell.org/package/haskell-src-exts-1.19.1/docs/Language-Haskell-Exts-Pretty.html) qui a à la fois une jolie imprimante et une imprimante exacte pour le code Haskell. –

Répondre

3

La façon habituelle de procéder est de passer une variable de précédence à votre fonction d'impression. En outre, vous devriez presque toujours préférer une jolie bibliothèque d'impression au lieu de simplement utiliser des chaînes brutes (à la fois pour des raisons de performance et de facilité). GHC est livré avec pretty et je recommande également le plus récent prettyprinter.

Utilisation de l'ancien (et en supposant type Name = String):

import Text.PrettyPrint.HughesPJ 

prettyType :: Type -> Doc 
prettyType = go 0 
    where 
    go :: Int -> Type -> Doc 
    go _ (TVar x) = text x 
    go _ (TLit n) = text n 
    go n (TLit "Fun" `TApp` l `TApp` r) = maybeParens (n > 0) (go 1 l <+> text "->" <+> go 0 r) 
    go n (l `TApp` r) = maybeParens (n > 1) (go 1 l <+> go 2 r)