### From Chen's Wiki

## Contents |

### Keywords

This post may help you go through the following tips:

- some concepts of monads
- Python function decorator
- Python operators
- Class inheritance

Although I am good at none of them.

### The ">>=" operator

The ">>=" infix operator is the real sugar in Haskell monad application. Looking at implementations of other languages, they are either prefixed or parathensis required or even both, like Python. e.g. bind(value, lambda x: ......) More frustrating for chaining.

Python does not support operator definition (I might misuse the term. what I mean is ...) nor creation of infix functions. So is it possible to make a counterpart? Luckily, Python do support some sort of operator overloading in a class definition.

### Challenges

- Suppose we can implement the operator ">>=", as a fact of using Python, the both sides of the operator should have the
**same class type**. Which implies that in "some_value >>= function", some_value should be in the same class (or a subclass, this is vital!) as the function. - There is no predefined ">>=" operator, the only possible way of making it is by
**composing/chaining**"__gt__" and "__ge__". However, they cannot be chained because both of them are binary operators and the there should be an object in between. So one of the two has to be**unary**. The unary operators are limited in number. So I have to pick "__invert__" and then "__rshift__" to make ">>~". Well, I call it equally good!

### Attacking the problems

1. Then let's make both the same type: Monad! For the right side, the function, I use Python decorator syntax to make the later application more formal.

class Monad(object): def __init__(self, function=lambda x: x): self.function = function def __rshift__(self): raise NotImplementedError def __invert__(self): return self def monadic(f): return Monad(f)

2. To illustrate, I implemented a Maybe monad in my paradigm. There comes the juice.

from monad import * class Maybe(Monad): def __init__(self, value): super(Maybe, self).__init__() self.value = value def __rshift__(self, other): return other.function(self.value) def __lshift__(self, other): return self.value def __repr__(self): if self.value == None: return 'Nothing' else: return 'Just(%r)' % self.value @classmethod def unit(cls, value): return cls(value) #unit is the Haskell return unit = Maybe.unit

You can see how ">>" gets chained by "~" to form ">>~" to mimic ">>=".

### Testing

By using the decorator syntax, it is acceptable faking the class type instead of telling the user explicitly. Tada, I *implemented* the Maybe monad in Python with relatively eye-candy syntax. (Sure, it may not be strictly a Monad but I just wanna show how to work around the critial part.)

@monadic def f(x): return unit(x+1) @monadic def g(x): return unit(x+2) m = Maybe(1) n = Maybe(None) #showing the Haskell >>= operator res = m >>~ f >>~ g print res #emit -> Just(4) #showing the Haskell >> operator res = n << f print res #emit -> Nothing

Source files can be found here.

### Comments

Anonymous User #1

Permalink |