The Reader monad pass the state you want to share between functions. Functions may read that state, but can't change it. The reader monad lets us access shared immutable state within a monadic context. In the Reader monad this shared state is called the environment.
The Reader is just a fancy name for a wrapped function, so this monad could also be called the Function monad, or perhaps the Callable monad. Reader is all about composing wrapped functions.
This IPython notebook uses the OSlash library for Python 3.4, aka Ø. You can install Ø using:
> pip3 install oslash
In [106]:
from oslash import Reader
unit = Reader.unit
A Reader wraps a function, so it takes a callable:
In [107]:
r = Reader(lambda name: "Hi %s!" % name)
In Python you can call this wrapped function as any other callable:
In [108]:
r("Dag")
Out[108]:
In [109]:
r = unit(42)
r("Ignored")
Out[109]:
In [117]:
r = Reader(lambda name: "Hi %s!" % name)
b = r | (lambda x: unit(x.replace("Hi", "Hello")))
b("Dag")
Out[117]:
In [122]:
r = Reader(lambda name: "Hi %s!" % name)
a = Reader.pure(lambda x: x + "!!!") * r
a("Dag")
Out[122]:
In [112]:
from oslash import MonadReader
asks = MonadReader.asks
ask = MonadReader.ask
In [113]:
r = ask() | (lambda x: unit("Hi %s!" % x))
r("Dag")
Out[113]:
In [114]:
r = asks(len)
r("banana")
Out[114]:
This example has been translated to Python from https://gist.github.com/egonSchiele/5752172.
In [115]:
from oslash import Reader, MonadReader
ask = MonadReader.ask
def hello():
return ask() | (lambda name:
unit("Hello, " + name + "!"))
def bye():
return ask() | (lambda name:
unit("Bye, " + name + "!"))
def convo():
return hello() | (lambda c1:
bye() | (lambda c2:
unit("%s %s" % (c1, c2))))
r = convo()
print(r("dag"))
That is it, that's the Reader monad for you in Python and Ø!
In [ ]: