Hacker News new | ask | show | jobs
by wvs 4752 days ago
"half 8 >>= half" might look a lot different from "half . half $ 8", but they're actually identical in underlying structure! The monad version is just using the wrong operator for visual comparison.

(.) composes two functions[1] but (>>=) composes a monad value with a monad function[2]. It'd be nice if we had an operator to compose two monad functions instead.

We can define that operator in terms of (>>=): "g <=< f = \x -> f x >>= g". You can check that the types work out[3]. Notice the great similarity to (.). (It's because they're both categorical composition operators of functions.)

Now we can write "half <=< half $ 8" and everything's dandy.

  [1]: (.) :: (b -> c) -> (a -> b) -> (a -> c)
  [2]: (>>=) :: m a -> (a -> m b) -> m b
  [3]: (<=<) :: (b -> m c) -> (a -> m b) -> (a -> m c)
2 comments

This is impressive, but it does not make me want to try Haskell more.
Ahaha, I agree. Abstract monad derivations are quite a foreboding introduction.
Absolutely right! (And you preempted my comment at the top level).

I think one reason for "monad hell" is unawareness about this kind of composable style.