When I am using Functors, Monads, and other Hakell constructs, if my code is more than just a couple of lines, I prefer using some syntactic sugar like do-notation. This makes it easier for me to follow the flow of the code. Outside of stylistic preference, is there any real advantage in using de-sugared blocks as opposed to the sugared alternative?
3 Answers
I think it's a shame that people are treating this question as dumb, especially because contrary to the strongest opinions being expressed here, the answer is yes, there can be an advantage to avoiding the do-sugar. Simon Marlow gives an excellent example of this in his talk about the Facebook Haxl project that he's working on. Here's a short, undoubtedly butchered version -- definitely look at his slides for more details!
Here's an example of a query Facebook might want to run:
numCommonFriends x y = do
fx <- friendsOf x
fy <- friendsOf y
return (length (intersect fx fy))
With the sugar, this is beautiful. Unfortunately, it's also badly sequential. It turns out you can design a Monad that makes the above possible, but badly underperformant, and the following non-sugary Applicative version significantly more performant:
numCommonFriends x y = length <$> liftA2 intersect (friendsOf x) (friendsOf y)
The point here being that the Applicative instance gets to run both friendsOf branches at once: it is statically clear that the second call to friendsOf
cannot depend on the first. This is a feat that monadic bind can't duplicate because the action computed in bind's second argument could depend on the result of the computation in the first argument.
Designing a new kind of sugar that allows such optimizations is an active research question at the moment, as far as I know.

- 145,880
- 9
- 220
- 380
-
4Ok, my interpretation of OPs question was to compare the do notation with its desugared equivalent, which would be something like `friendsOf x >>= (\fx -> friendsOf y >>= (\fy -> return (length (intersect fx fy))))` as far as I understand (or potentially a nicer variant using `liftM2`). Your interpretation gives a much more interesting perspective, I must admit. I'm still not sure this is what OP meant, but then again we're not mainly here to help people but to document knowledge and this is definitely something more Haskell programmers should be aware of. – Niklas B. Mar 01 '14 at 04:11
-
Yeah, the elegance and clarity of applicative (in most cases) is my motivation to use it because it most directly resembles what you are doing when parsing into a tree. – Mike Menzel Mar 01 '14 at 11:49
-
I hadn't really thought about the parallel evaluation aspect. Thanks for the pointer to the paper. – Mike Menzel Mar 01 '14 at 11:56
-
@MikeMenzel Keep in mind that parallel evaluation is one example; but there are many examples even of sequential computations where a monadic bind is slower than the Applicative analog -- and even cases where the slowdown is asymptotic. – Daniel Wagner Mar 01 '14 at 15:36
Well no. The whole point of sugaring is that it desugars to exactly the desugared version, so there can't be any non-stylistic advantage. It might be good for you to get used to the desugared notation so that you can follow it when it is stylistically clearer, but you won't get any performance benefits or anything, because the code is identical.

- 89,153
- 8
- 140
- 205
Daniel argues for desugaring from a performance standpoint, amalloy argues against desugaring from a readability standpoint.
I'd argue that sometimes, the desugared version is just more readable i.e. compare
echo :: IO ()
echo = do
ln <- getLine
putStrLn ln
to
echo :: IO ()
echo = putStrLn =<< getLine

- 14,902
- 5
- 47
- 92
-
This have an disadvantage that `putStrLn` appear before `getLine` whilst the former got executed later. To fix this, say `getLine >>= putStrLn`, this is even more readable. – Earth Engine Jul 15 '14 at 03:08
-
@EarthEngine That's true if you're thinking in terms of "first this runs, and then that runs". I'm reading it as `putStrLn $getLine` where `$getLine` is the string I get from `getLine` - so I read it more in terms of "here's what I'm gonna do and here's where the inputs for that come from". – Cubic Jul 15 '14 at 21:22