4 ms·
A reader is just an interface that allows you to build up a computation that will eventually take an environment as a parameter and return a value. Here's the
by itishappy 11mo ago
A reader is just an interface that allows you to build up a computation that will eventually take an environment as a parameter and return a value.
Here's the magic:
newtype Reader env a = Reader { runReader :: env -> a }
ask = Reader $ \x -> x
instance Functor (Reader env) where
fmap f (Reader g) = Reader $ \x -> f (g x)
instance Applicative (Reader env) where
pure x = Reader (\_ -> x)
ff <*> fx = Reader $ \x -> (runReader ff x) (runReader fx x)
instance Monad (Reader env) where
(Reader f) >>= g = Reader $ \x -> runReader (g (f x)) x
That Monad instance might be the scariest bit if you're unfamiliar with Haskell. The (>>=) function takes a Monad (here a Reader) and a continuation to call on it's contents. It then threads the environment through both.
Might be used like this:
calc :: Reader String Int
calc = do
input <- ask
pure $ length input
test :: Int
test = runReader calc "Test"
-- returns: 4
Not sure how this compares to Zig!
https://stackoverflow.com/questions/14178889/what-is-the-purpose-of-the-reader-monad https://stackoverflow.com/questions/14178889/what-is-the-pur...
Edit: Added Applicative instance so code runs on modern Haskell. Please critique! Also added example.
- itishappy 11mo agoHere'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)