Tiny haskell code with high feature density
Trying to get a handle on monads in haskell, I found myself punching out this cute one-liner. It neatly demonstrates many of haskell’s cooler features in a remarkably tiny space.
[1..5] >>= return . (+5) -- outputs: [6,7,8,9,10]
And it works something like this:
[1..5] builds the list [1, 2, 3, 4, 5]
>>= is one of those crazy monad operators. Generally: a monad is a kind of container. The >>= operator extracts a value from that container, and passes it to the function on the right. The function on the right has to be somewhat special: it must take that value, operate on it, and then insert it back into the original type of container.
In this example, the monad/container is a list. So, the >>= operator takes a value from the list, applies that function on the right to it, and inserts the result back into a list (at the end, all those little lists are concatenated back into a single list).
Right.
Reading the function on the right from right to left. (+5) is a partially applied addition function. It takes a value, and returns that value plus 5. That function is composed with the return function, which in haskell inserts a value back into its monad container — basically inserting, say, 6 back into the list.
A haskell expert might quibble with bits of my description, but that’s generally what’s going on. Quite the assortment of features: a list building syntatical form, monads, function composition, point-free style, and partially applied functions.
One last thing. For your viewing pleasure, each of the following lines of code have the exact same effect as the above. I do this last because it’s interesting, but also because I want to stress that nobody would actually write code like the above. It’s just an interesting exercise — one that helped me understand monads a little bit better.
[1..5] >>= \n -> return (n + 5) [1..5] >>= \n -> [n + 5] map (\n -> n + 5) [1..5] map (+5) [1..5] fmap (+5) [1..5]