How to get Text.PrettyPrint.HughesPJ.fsep behaviour in Text.PrettyPrint.Leijen?
haskell, pretty-print
Solution
A simple solution is to use `hsep` inside the parentheses
λ> L.fillSep $ map (\d -> L.parens $ L.hsep $ replicate 4 d) $ map (L.text . show) [1..10]
(1 1 1 1) (2 2 2 2) (3 3 3 3)
(4 4 4 4) (5 5 5 5) (6 6 6 6)
(7 7 7 7) (8 8 8 8) (9 9 9 9)
(10 10 10 10)
But that means that the inner document will always be printed horizontally.
Here is a function that is closer to the HughesPJ behavior:
fsep :: [L.Doc] -> L.Doc
fsep = foldl1 (\x y -> x L.<> (L.group $ L.line L.<> y))
λ> fsep $ map (\d -> L.parens $ L.fillSep $ replicate 4 d) $ map (L.text . show) [1..10]
(1 1 1 1) (2 2 2 2) (3 3 3 3)
(4 4 4 4) (5 5 5 5) (6 6 6 6)
(7 7 7 7) (8 8 8 8) (9 9 9 9)
(10 10 10 10)
What `group` does is put the output on a single line by changing all `line`s to `space` if the resulting output fits on the current line, while keeping the original formating otherwise. So `fsep` outputs the start of a list, and if the next item completely fits on the same line, then it is appended to that line. Otherwise a newline is inserted before the next list element.
In general, I often find it easier to control the output by using `group` manually, instead of relying on `softline` and `</>`.
Problem
I am switching from H to L ``` import qualified Text.PrettyPrint.HughesPJ as H import qualified Text.PrettyPrint.Leijen as L ``` and I have problems translating H.fsep ("paragraph fill"). This is what I want: ``` H.fsep $ map ( \ d -> H.parens $ H.fsep $ replicate 4 d ) $ map (H.text . show) [1..10] (1 1 1 1) (2 2 2 2) (3 3 3 3) (4 4 4 4) (5 5 5 5) (6 6 6 6) (7 7 7 7) (8 8 8 8) (9 9 9 9) (10 10 10 10) ``` But I only get this: ``` L.fillSep $ map ( \ d -> L.parens $ L.fillSep $ replicate 4 d ) $ map (L.text . show) [1..10] (1 1 1 1) (2 2 2 2) (3 3 3 3) (4 4 4 4) (5 5 5 5) (6 6 6 6) (7 7 7 7) (8 8 8 8) (9 9 9 9) (10 10 10 10) ``` (the formatting of the inner documents is not respected) or this: ``` L.fillSep $ map ( \ d -> L.parens $ L.align $ L.fillSep $ replicate 4 d ) $ map (L.text . show) [1..10] (1 1 1 1) (2 2 2 2) (3 3 3 3) (4 4 4 4) (5 5 5 5) (6 6 6 6) (7 7 7 7) (8 8 8 8) (9 9 9 9) (10 10 10 10) ``` which is ugly.