ppPat :: Applicative f
      => (Prec -> e -> f Doc)
      -> Prec -> Pat e -> f Doc
ppPat f p pat =
  case pat of
    PVar i _ _ -> pure (text i)
    PUnused{}  -> pure (char '_')
    PCtor c pl -> ppAppList p (ppIdent c) <$> traverse (ppPat f PrecArg) pl
    PUnit      -> pure $ text "()"
    PPair x y  -> ppParens (p > PrecApp) <$>
                  (infixDoc "#" <$> ppPat f PrecApp x <*> ppPat f PrecApp y)
    PRecord m  -> ppRecordF (ppPat f PrecNone) m
ppPat :: Applicative f
      => (Prec -> e -> f Doc)
      -> Prec -> Pat e -> f Doc
ppPat f p pat =
  case pat of
    PVar i _ _ -> pure (text i)
    PUnused{}  -> pure (char '_')
    PCtor c pl -> ppAppList p (ppIdent c) <$> traverse (ppPat f PrecArg) pl
    PUnit      -> pure $ text "()"
    PPair x y  -> ppParens (p > PrecApp) <$>
                  (infixDoc "#" <$> ppPat f PrecApp x <*> ppPat f PrecApp y)
    PRecord m  -> ppRecordF (ppPat f PrecNone) m
ppPat f p pat =
  case pat of
    PVar i _ _ -> pure (text i)
    PUnused{}  -> pure (char '_')
    PCtor c pl -> ppAppList p (ppIdent c) <$> traverse (ppPat f PrecArg) pl
    PUnit      -> pure $ text "()"
    PPair x y  -> ppParens (p > PrecApp) <$>
                  (infixDoc "#" <$> ppPat f PrecApp x <*> ppPat f PrecApp y)
    PRecord m  -> ppRecordF (ppPat f PrecNone) m