Comment by itishappy
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-pur...
Edit: Added Applicative instance so code runs on modern Haskell. Please critique! Also added example.
Here's a minimal python translation of the important bits:
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.