Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top