prettyprinter
prettyprinter copied to clipboard
Lifted Pretty classes
Per #39, this PR defines Pretty1
& Pretty2
classes, lifting Pretty
to * -> *
& * -> * -> *
respectively, in the same manner as Show1
& Show2
.
I’ve also defined a few instances of these new classes, as well as an instance of Pretty
for Either a b
, since it seemed incomplete to provide a Pretty2
instance for (,)
but not for Either
, and thereafter seemed incomplete to provide only lifted instances for Either
.
I’ve confirmed that the tests (including doctests) all pass, but haven’t added any new tests since the instances are quite minimal.
I think the key to the Pretty1 documentation should be showing how it is useful without going into too much detail. Like »here we define Pretty without using Pretty1, see how Pretty1 makes our lives much easier?«
I quite like this idea! I think the []
instance isn’t gonna cut it, because it’s almost identical to the Pretty
instance. Unfortunately, I’m having difficulty coming up with a better example. My own motivating examples tend to involve GADTs, signature functors, and/or functor composition, e.g.:
{-# LANGUAGE GADTs #-}
data Expr a = Plus a a | Times a a | Const Int
newtype Fix f = Fix (f (Fix f))
data FreeF f a b = Free (f b) | Pure a
type Free f a = Fix (FreeF f a)
instance Pretty1 Expr where
liftPretty p _ (Plus a b) = parens $ p a <+> pretty '+' <+> p b
liftPretty p _ (Times a b) = p a <+> pretty '*' <+> p b
liftPretty _ _ (Const i) = pretty i
instance Pretty1 f => Pretty2 (Free f) where
liftPretty2 pA _ pB plB = go
where go (Pure a) = pA a
go (Free f) = liftPretty pB plB f
instance (Pretty1 f, Pretty a) => Pretty1 (Free f) where
liftPretty = liftPretty2 pretty prettyList
instance Pretty1 f => Pretty (Fix f) where
pretty (Fix f) = liftPretty pretty prettyList f
vs.
{-# LANGUAGE UndecidableInstances #-}
instance (Pretty (f b), Pretty a) => Pretty (FreeF f a b) where
pretty (Pure a) = pretty a
pretty (Free f) = pretty f
instance Pretty (f (Fix f)) => Pretty (Fix f) where
pretty (Fix f) = pretty f
This seems a little overboard for the docs, but I’m not sure what would be a better example :confused: What do you think?
Actually, this brings up a new law:
Pretty1 f
andPretty (f a)
should result in identical behavior! :-)
I suppose that if we were willing to compromise on that by accepting strange behaviour with String
:
>>> liftPretty pretty "hello"
[h, e, l, l, o]
then we’d be able to pare things down significantly. I am having trouble imagining a situation where you’d use liftPretty
on a String
, to be honest; but I’ll defer to your preference.
Back from summer hiatus! Sorry for the late reply. I don’t think String
is important enough to break a leg over it to be honest! A short remark about this misalignment would be a good idea anyway, since for example Maybe a
has a special case for lists as well.
Your documentation looks good, but it’s too verbose to show it in the default view. But good news, I recently found out that Haddock allows collapsible sections via -- ==== <title>
(example)! Putting the long and somewhat complicated example in there would be fine: it allows interested parties to see them, while not being interrupting for the casual reader.
Back from summer hiatus! Sorry for the late reply.
No apologies necessary; hope you had a lovely break!
I don’t think
String
is important enough to break a leg over it to be honest! A short remark about this misalignment would be a good idea anyway, since for exampleMaybe
a has a special case for lists as well.
Done and done 👍
Your documentation looks good, but it’s too verbose to show it in the default view. But good news, I recently found out that Haddock allows collapsible sections via
-- ==== <title>
(example)!
Oh, very cool! Thanks for sharing that gem 😊
Putting the long and somewhat complicated example in there would be fine: it allows interested parties to see them, while not being interrupting for the casual reader.
Excellent. It took me a bit to figure out how to make doctest accept multi-line input for the instances, but I’ve now added that and it’s looking good 👍
I appreciate you taking the time to workshop this PR with me. IMO the code has benefitted greatly from it! Let me know what you think of the latest revisions.