prettyExpression :: Bool -> (f -> PP.Doc) -> (v -> PP.Doc) -> Expression f v tp -> PP.Doc
prettyExpression showLabel ppFun ppVar = pp id where
  pp _ (Var v _) = ppVar v
  pp _ (Fun f _ l)
    | showLabel = ppFun f PP.<> PP.text "@" PP.<> PP.int (uniqueToInt l)
    | otherwise = ppFun f 
  pp _ (Pair _ t1 t2) = ppTuple (pp id t1, pp id t2)
  pp par (Apply _ t1 t2) =
    par (pp id t1 PP.</> pp PP.parens t2)
  pp par (If _ tg tt te) =
    par (PP.text "if" PP.<+> pp id tg
         // PP.hang 2 (PP.text "then" PP.<+> pp id tt)
         // PP.hang 2 (PP.text "else" PP.<+> pp id te))
  pp par (LetP _ t1 ((x,_),(y,_)) t2) =
    par (PP.align (PP.text "let" PP.<+> ppTuple (ppVar x, ppVar y)
                   PP.<+> PP.text "=" PP.<+> pp id t1
                   PP.<$> PP.hang 3 (PP.text "in" PP.<+> pp id t2)))
prettyExpression :: Bool -> (f -> PP.Doc) -> (v -> PP.Doc) -> Expression f v tp -> PP.Doc
prettyExpression showLabel ppFun ppVar = pp id where
  pp _ (Var v _) = ppVar v
  pp _ (Fun f _ l)
    | showLabel = ppFun f PP.<> PP.text "@" PP.<> PP.int (uniqueToInt l)
    | otherwise = ppFun f 
  pp _ (Pair _ t1 t2) = ppTuple (pp id t1, pp id t2)
  pp par (Apply _ t1 t2) =
    par (pp id t1 PP.</> pp PP.parens t2)
  pp par (If _ tg tt te) =
    par (PP.text "if" PP.<+> pp id tg
         // PP.hang 2 (PP.text "then" PP.<+> pp id tt)
         // PP.hang 2 (PP.text "else" PP.<+> pp id te))
  pp par (LetP _ t1 ((x,_),(y,_)) t2) =
    par (PP.align (PP.text "let" PP.<+> ppTuple (ppVar x, ppVar y)
                   PP.<+> PP.text "=" PP.<+> pp id t1
                   PP.<$> PP.hang 3 (PP.text "in" PP.<+> pp id t2)))
prettyExpression showLabel ppFun ppVar = pp id where
  pp _ (Var v _) = ppVar v
  pp _ (Fun f _ l)
    | showLabel = ppFun f PP.<> PP.text "@" PP.<> PP.int (uniqueToInt l)
    | otherwise = ppFun f 
  pp _ (Pair _ t1 t2) = ppTuple (pp id t1, pp id t2)
  pp par (Apply _ t1 t2) =
    par (pp id t1 PP.</> pp PP.parens t2)
  pp par (If _ tg tt te) =
    par (PP.text "if" PP.<+> pp id tg
         // PP.hang 2 (PP.text "then" PP.<+> pp id tt)
         // PP.hang 2 (PP.text "else" PP.<+> pp id te))
  pp par (LetP _ t1 ((x,_),(y,_)) t2) =
    par (PP.align (PP.text "let" PP.<+> ppTuple (ppVar x, ppVar y)
                   PP.<+> PP.text "=" PP.<+> pp id t1
                   PP.<$> PP.hang 3 (PP.text "in" PP.<+> pp id t2)))