Comment by itishappy
Here's a minimal python translation of the important bits:
class Reader:
def __init__(self, func):
self.run = func
def pure(x):
return Reader(lambda _: x)
def bind(self, f):
return Reader(lambda env: f(self.run(env)).run(env))
ask = Reader(lambda env: env)
def calc():
return ask.bind(lambda input_str:
Reader.pure(len(input_str)))
test = calc().run("test")
print(test)
Admittedly this is a bit unwieldy in Python. Haskell's `do` notation desugars to repeated binds (and therefore requires something to be a Monad), and does a lot of handiwork. -- this:
calc :: Reader String Int
calc = do
input <- ask
pure $ length input
-- translates to:
calc' :: Reader String Int
calc' = ask >>= (\input -> pure $ length input)