[Haskell-cafe] Confusion on the third monad law when using lambda
abstractions
Jake McArthur
jake.mcarthur at gmail.com
Thu Jun 18 09:34:45 EDT 2009
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
More information about the Haskell-Cafe
mailing list