quchen / prettyprinter

A modern, extensible and well-documented prettyprinter.
BSD 2-Clause "Simplified" License
295 stars 36 forks source link

Choice between non-flat documents #152

Open sjakobi opened 4 years ago

sjakobi commented 4 years ago

How do I construct a document that renders as

abcd
efgh

when the page is wide enough, or alternatively as

ab
cd
ef
gh

?

Using the public API I would try this:

x = "abcd" <> hardline <> "efgh"
y = concatWith (\a b -> a <> hardline <> b) ["ab", "cd", "ef", "gh"]
doc = group (flatAlt y x)

But this will always render y:

> putDoc doc
ab
cd
ef
gh

…because group attempts and fails to flatten the preferred version:

https://github.com/quchen/prettyprinter/blob/57ced7bf35ef581a247d79a4a1b803b384845cc4/prettyprinter/src/Data/Text/Prettyprint/Doc/Internal.hs#L580-L585

https://github.com/quchen/prettyprinter/blob/57ced7bf35ef581a247d79a4a1b803b384845cc4/prettyprinter/src/Data/Text/Prettyprint/Doc/Internal.hs#L627-L628

https://github.com/quchen/prettyprinter/blob/57ced7bf35ef581a247d79a4a1b803b384845cc4/prettyprinter/src/Data/Text/Prettyprint/Doc/Internal.hs#L653-L657

This is an interesting difference to ansi-wl-pprint which doesn't attempt to flatten the "nice" FlatAlt branch.

If I resort to the internals, it's easy:

doc' = Union x y
> putDocW 4 doc'
abcd
efgh
> putDocW 2 doc'
ab
cd
ef
gh

Is there a different way to achieve this with the public API? Is this simply a problem that doesn't arise in the "real world"?

sjakobi commented 4 years ago

If we want to change the way group behaves here, I see two basic options:

  1. Don't flatten the "nice" FlatAlt branch. Users might then have to flatten the alternative themselves, using group probably, or a new public flat[ten].
  2. Keep trying to flatten the FlatAlt branch, but instead of producing Fail when encountering a hard Line, simply keep it.

If we don't want to change the way group behaves, maybe we can consider another variant of the prefer combinator I had proposed in https://github.com/quchen/prettyprinter/issues/138:

prefer = Union
sjakobi commented 4 years ago

2. Keep trying to flatten the FlatAlt branch, but instead of producing Fail when encountering a hard Line, simply keep it.

Probably not a good idea: We might end up embedding a multi-line chunk (like a Dhall multiline string) in a layout that is meant for single lines only.

sjakobi commented 4 years ago

I'm wondering whether we should add an non-flattening variant of flatAlt:

alt a b  = Union b a