I'd just like to chime in briefly here, because I hold many unpopular opinions and this is one of them and you asked so nyaaaaah.
Admitted: the community appears to more or less agree that f <$> x <*> y <*> z
style is better. But I actually prefer pure f <*> x <*> y <*> z
. I find it relatively common that lines written in applicative style tend towards being longish, since each argument is often itself a call to a function, so:
fancyParser = FancyConstructor <$> fooParserWith 7 blag <*> barParserSep "hi" (sizzleParser pop) <*> bazParser
-- OR
fancyParser = pure FancyConstructor <*> fooParserWith 7 blag <*> barParserSep "hi" (sizzleParser pop) <*> bazParser
For readability, I often split the arguments onto their own lines; I find the visual separation makes it clearer where the argument boundaries are, gives my eyes a bit of a rest, and makes it less likely that the line will wrap in an ugly way:
fancyParser = FancyConstructor
<$> fooParserWith 7 blag
<*> barParserSep "hi" (sizzleParser pop)
<*> bazParser
-- OR
fancyParser = pure FancyConstructor
<*> fooParserWith 7 blag
<*> barParserSep "hi" (sizzleParser pop)
<*> bazParser
In this form, I think it's quite clear why I prefer pure
/<*>
: it makes for a completely consistent line beginning. This consistency is visually appealing, for one. But more importantly, when I inevitably refactor FancyConstructor
to rearrange the order of fields, or insert a new field at the beginning, I can use line-wise editing commands with complete impunity. Certain regex searches become slightly easier as well. It only eliminates a little bit of friction... but eliminating small frictions is one important part of doing programming in the large.
P.S. Other unpopular examples of ways to get consistent line formats that I've found handy:
-- orthodox
foo a b c d
= f
. g
. h
-- dmwit
foo a b c d = id
. f
. g
. h
-- orthodox
foo a b c d =
[ x
, y
, z
]
-- dmwit
foo a b c d = tail [undefined
, x
, y
, z
]
-- orthodox
bad = die
$ "some kind of "
<> "error that is best described "
<> "on multiple lines"
-- dmwit
bad = die $ mempty {- or "", if appropriate -}
<> "some kind of "
<> "error that is best described "
<> "on multiple lines"
-- orthodox
foo
:: arg1
-> arg2
-> result
-- dmwit
foo ::
arg1 ->
arg2 ->
result
-- orthodox
foo a b c d =
[ t
| u <- v
, w <- x
, y <- z
]
-- dmwit
foo a b c d =
[ t | _ <- [()]
, u <- v
, w <- x
, y <- z
]