From Chen's Wiki

Jump to: navigation, search



My new and much more valueable post talking about monad implementation can be found here

The question

Evantually here it comes!

How do you feed a function which take a normal value and return a value under context with a value under context?

Defination in Haskell

We want this:

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

Formally, the whole thing is:

class Monad m where  
        return :: a -> m a  
        (>>=) :: m a -> (a -> m b) -> m b  
        (>>) :: m a -> m b -> m b  
        x >> y = x >>= \_ -> y  
        fail :: String -> m a  
        fail msg = error msg  

However, we just need to focus on the >>= which reads bind and the return.

return does nothing with the imperative return in Python. You can see that it just does the same thing as pure.

Python example

def unit(x):                    #the "return"
        return [x]

def bind(x, f):                #the ">>="
        return flatten(map(f, x))

def flatten(xs):
        return [x for sub in xs for x in sub]

print bind([1, 2], lambda x: unit(x+1))
print bind([1, 2], lambda x:
          bind([1, 2], lambda y: unit((x, y))))

#[2, 3]
#[(1, 1), (1, 2), (2, 1), (2, 2)]

It is actually straightforward. The only tricky part here for a list monad is that a use of flatten. This makes the return value still the same with the original function.

Things making it ugly are

  1. It is hard to make a infix ">>=" operator in Python. Let's try working around this [a bit]
  2. Python does not support currying by default so we have to use a chain of lambdas.

Full version

I have tried to describe these functional concepts step by step, starting from the functors in another article. Functor, Applicative, Monads in Python


Add your Comment
Chen's Wiki welcomes all comments. If you don't want to be anonymous, register or log in. It's free.