Hans van Thiel wrote:
The only place I've ever seen Kleisli composition, or its flip, used is
in demonstrating the monad laws. Yet it is so elegant and, even having
its own name, it must have some practical use. Do you, or anybody else,
have some pointers?

I only just started finding places to use it myself, admittedly, but I now think it has common use and it fairly easy to spot. I'll take it slow, if not for you, as you seem to have a grasp on what these operators are already, then for other readers. Consider a function of this form:

    foo x = a $ b $ c $ d $ e $ f x

The obvious thing to do here is to simply drop the `x` from both sides by using `(.)` instead of `($)`:

        ==>

    foo x = a . b . c . d . e . f $ x

        ==>

    foo = a . b . c . d . e . f

Now, consider this:

    bar x = a =<< b =<< c =<< d =<< e =<< f x

If you compare that to the original version of `foo` above, you see that it is similar. In fact, looking at the types for `($)` and `(=<<)`:

    ($)   ::            (a ->   b) -> (  a ->   b)
    (=<<) :: Monad m => (a -> m b) -> (m a -> m b)

So, `(=<<)` is just like `($)` except for the information carried along by the monad.

Anyway, the "obvious" thing to do is to drop the `x` from both sides of the definition for `bar`. To do that with `foo` earlier, we had to substitute `($)` with `(.)`. What we are looking for is an equivalent operator for monads:

    (.)   ::            (b      c) -> (a ->   b) -> (a ->   c)
    (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)

So we now can do this:

        ==>

    bar x = a <=< b <=< c <=< d <=< e <=< f $ x

        ==>

    bar = a <=< b <=< c <=< d <=< e <=< f

And we're done.

Generally, you can transform anything of the form:

    baz x1 = a =<< b =<< ... =<< z x1

into:

    baz = a <=< b <=< ... <=< z

If you aren't already using `(=<<)` much more than `(>>=)` or do-notation then you will have a harder time finding opportunities to use `(<=<)` because only `(=<<)` has the same flow as function application, which allows your mind to play the appropriate association games. I suppose you could also replace `(>>=)` with `(>>>)`, but this would likely require more mental adjustment than replacing `(=<<)` with `(<=<)`.

- Jake
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to