lines package:hedgehog

Splits the argument into a list of lines stripped of their terminating \n characters. The \n terminator is optional in a final non-empty line of the argument string. For example:
>>> lines ""           -- empty input contains no lines
[]

>>> lines "\n"         -- single empty line
[""]

>>> lines "one"        -- single unterminated line
["one"]

>>> lines "one\n"      -- single non-empty line
["one"]

>>> lines "one\n\n"    -- second line is empty
["one",""]

>>> lines "one\ntwo"   -- second line is unterminated
["one","two"]

>>> lines "one\ntwo\n" -- two non-empty lines
["one","two"]
When the argument string is empty, or ends in a \n character, it can be recovered by passing the result of lines to the unlines function. Otherwise, unlines appends the missing terminating \n. This makes unlines . lines idempotent:
(unlines . lines) . (unlines . lines) = (unlines . lines)
Appends a \n character to each input string, then concatenates the results. Equivalent to foldMap (s -> s ++ "\n").
>>> unlines ["Hello", "World", "!"]
"Hello\nWorld\n!\n"
Note that unlines . lines /= id when the input is not \n-terminated:
>>> unlines . lines $ "foo\nbar"
"foo\nbar\n"