Closed skilly-lily closed 1 year ago
On the surface, and without any detailed knowledge of the prettyprinter internals, it seems like an identity instance is trivial to add:
instance Pretty (Doc ann) where pretty = id
Unfortunately it's not quite this easy:
ghci> instance Pretty (Doc ann) where pretty = id
<interactive>:4:42: error:
• Couldn't match type ‘ann1’ with ‘ann’
Expected: Doc ann -> Doc ann1
Actual: Doc ann -> Doc ann
‘ann1’ is a rigid type variable bound by
the type signature for:
pretty :: forall ann1. Doc ann -> Doc ann1
at <interactive>:4:33-38
‘ann’ is a rigid type variable bound by
the instance declaration
at <interactive>:4:10-25
• In the expression: id
In an equation for ‘pretty’: pretty = id
In the instance declaration for ‘Pretty (Doc ann)’
• Relevant bindings include
pretty :: Doc ann -> Doc ann1 (bound at <interactive>:4:33)
Is there a trick to make the annotation type of the input and output Doc
s match up?
Looking through the history, I noticed that there was a general instance before, but one that removed all annotations:
instance Pretty (Doc ann) where pretty = unAnnotate
This was surprising to me, since it wasn't clear why using
pretty
should remove pre-existing annotations.
The relevant commit seems to be https://github.com/quchen/prettyprinter/commit/b653d592a337fa083859f79b0d893174a2d805a5. This was long before my involvement in this project, but it seems that the removal was motivated by the (performance) pitfall documented in the instance haddocks:
since this un-annotates its argument, nesting it means multiple, potentially costly, traversals over the 'Doc'.
Maybe @quchen can provide more context.
To get back to the instance, I wonder how to best avoid the unAnnotate
pass. Maybe we could consider having an instance for Doc
s that cannot contain annotations, e.g.
instance Pretty (Doc Void) where
pretty = unsafeCoerce
(dhall
uses a similar trick.)
Question
Why is there no
Pretty
instance forDoc ann
which functions as the identity?On the surface, and without any detailed knowledge of the prettyprinter internals, it seems like an identity instance is trivial to add:
Looking through the history, I noticed that there was a general instance before, but one that removed all annotations:
This was surprising to me, since it wasn't clear why using
pretty
should remove pre-existing annotations.Rationale
Currently, we have a
prettyprinter
-based logging system that has the following form (simplified):Note the call to
pretty
in thethen
portion of the if statement. Those are absolutely everywhere in the codebase.What we'd like to do is this:
Without the pretty instance, we're forced to do this, which is harder to migrate to, and is less obvious to developers:
Note the required use of both
log
andlog'
. This is particularly ugly.