Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Sequencing in Functional Programming

I'm mostly a practical guy but I find this interesting.

I have been thinking about monadic sequencing and there are a few things that I need clarified. So at the risk of sounding silly here it is:

The monadic member bind

bind :: m b -> (b -> m c) -> m c

can sequence "actions" giving you explicit access to intermediate values.

How does this give me more than the categorical member (.):

(.) :: cat b c -> cat a b -> cat a c

With this I can sequence and get access to intermediate values. After all (f . g) x = f(g (x)).

Why do I need bind for sequencing if I can sequence with (.)?

like image 530
Eric Avatar asked Oct 13 '12 20:10

Eric


1 Answers

You're on the right track. Every monad gives rise to so-called Kleisli category. For every monad m its corresponding Kleisli category has arrows a -> m b and they can be composed using >=>, which is defined as

f >=> g     = \x -> f x >>= g

Kleisli type encapsulates this in Haskell type system, you can see that it has instance

instance Monad m => Category (Kleisli m) where
    id = Kleisli return
    (Kleisli f) . (Kleisli g) = Kleisli (g >=> f)

So sequencing computations within this category is just sequencing operations using >=>, which can be expressed equivalently using >>=.

We define monads using return and >>= because it's more convenient, but we could define them as well using return and >=> if we wanted.

(See also my answer to Different ways to see a monad.)

like image 69
Petr Avatar answered Nov 15 '22 10:11

Petr