The reader monad encodes read-only access to an environment e: newtype Reader e a = Reader (e -> a), i.e. the Exponential Object .
instance Monad (Reader e) where
ma >>= k = Reader (\e -> let a = runReader ma e in runReader (k a) e)
return a = Reader (\e -> a)Bind threads the same environment into both computations; return ignores it. A function a -> Reader e b is a curried (a, e) -> b — a delayed effect, a script interpreted by runReader.
Sources: DaoFP §14.1 (“Environment”), §14.4, Exercise 14.4.1 (
E e a = e -> Maybe a, a reader/maybe combination); §15.3 (the reader functor is of the currying adjunction), §17.1 (hom functor); CTfS Application 5.3.1.2, Examples 5.3.2.6, 5.3.3.4
- Who did the experiment? (CTfS Application 5.3.1.2, Example 5.3.3.4): with the set of experimenters, a Kleisli arrow is an experiment whose outcome may depend on who performs it (a psychology experiment ). Kleisli composition feeds one experiment’s result into the next with the same experimenter; ordinary functions embed as “every experimenter gets the same result”.
Reader eis the Hom Functor ; its monad structure comes from the fact that is a comonoid (copy/delete) in a cartesian category — the environment can be duplicated and passed to both parts of a bind.- Combined with
Maybeit givesE e a = e -> Maybe a(DaoFP Exercise 14.4.1); combined with a product it gives the State Monad.
Docs: plain Julia — Catlab has no dedicated API for this; related: Catlab v0.16 docs · GATlab standard library
# Reader: computations are functions of an environment
ret(a) = env -> a
bind(ma, k) = env -> k(ma(env))(env)
ask = env -> env
greet = bind(ask, name -> ret("hello, $name"))
greet("Daniel") # "hello, Daniel"import Mathlib
#check @ReaderT -- ReaderT ρ m α := ρ → m α ; Reader ρ = ReaderT ρ Id
#check @ReaderT.bind
#check @MonadReader.readnewtype Reader e a = Reader (e -> a)
runReader :: Reader e a -> e -> a
runReader (Reader h) e = h e
instance Functor (Reader e) where fmap f (Reader h) = Reader (f . h)
instance Applicative (Reader e) where
pure a = Reader (const a)
Reader f <*> Reader g = Reader (\e -> f e (g e))
instance Monad (Reader e) where
ma >>= k = Reader (\e -> runReader (k (runReader ma e)) e)
ask :: Reader e e
ask = Reader id