patuni/Kit.lhs

92 lines
2.4 KiB
Text
Raw Normal View History

2024-06-23 12:03:32 -04:00
This module defines some basic general purpose kit, in particular
backwards lists and a typeclass of things that can be pretty-printed.
> module Kit ( bool
> , Bwd(..)
> , (<><)
> , (<>>)
> , trail
> , Size(..)
> , prettyAt
> , prettyLow
> , prettyHigh
> , wrapDoc
> , runPretty
> , pp
> , ppWith
> , Pretty(..)
> , between
> , commaSep
> , module PP
> ) where
> import Control.Monad.Reader
> import Text.PrettyPrint.HughesPJ as PP hiding (($$), first)
> import Unbound.Generics.LocallyNameless
> bool :: a -> a -> Bool -> a
> bool no yes b = if b then yes else no
> data Bwd a = B0 | Bwd a :< a
> deriving (Eq, Show, Functor, Foldable)
> (<><) :: Bwd a -> [a] -> Bwd a
> xs <>< [] = xs
> xs <>< (y : ys) = (xs :< y) <>< ys
> (<>>) :: Bwd a -> [a] -> [a]
> B0 <>> ys = ys
> (xs :< x) <>> ys = xs <>> (x : ys)
> trail :: Bwd a -> [a]
> trail = (<>> [])
> data Size = ArgSize | AppSize | PiSize | LamSize
> deriving (Bounded, Enum, Eq, Ord, Show)
> prettyAt ::
> (Pretty a, Applicative m, LFresh m, MonadReader Size m) => Size -> a -> m Doc
> prettyAt sz = local (const sz) . pretty
> prettyLow, prettyHigh ::
> (Pretty a, Applicative m, LFresh m, MonadReader Size m) => a -> m Doc
> prettyLow = prettyAt minBound
> prettyHigh = prettyAt maxBound
> wrapDoc :: MonadReader Size m => Size -> m Doc -> m Doc
> wrapDoc dSize md = do
> d <- md
> curSize <- ask
> return $ if dSize > curSize then parens d else d
> runPretty :: ReaderT Size LFreshM a -> a
> runPretty = runLFreshM . flip runReaderT maxBound
> pp :: Pretty a => a -> String
> pp = render . runPretty . pretty
> ppWith :: (a -> ReaderT Size LFreshM Doc) -> a -> String
> ppWith f = render . runPretty . f
> class Pretty a where
> pretty :: (Applicative m, LFresh m, MonadReader Size m) => a -> m Doc
> instance Pretty (Name x) where
> pretty n = return $ text $ show n
> instance (Pretty a, Pretty b) => Pretty (Either a b) where
> pretty (Left x) = (text "Left" <+>) <$> pretty x
> pretty (Right y) = (text "Right" <+>) <$> pretty y
> instance Pretty () where
> pretty () = return $ text "()"
> between :: Doc -> Doc -> Doc -> Doc
> between d x y = x <+> d <+> y
> commaSep :: [Doc] -> Doc
> commaSep = hsep . punctuate comma