Reputation: 9761
Although I understand the implementation of the reader monad of which I give 2 of the most prominent way to do it below:
case class Reader[R, A](run: R => A)
def readerMonad[R] = new Monad[({type f[x] = Reader[R,x]})#f] {
def unit[A](a: => A): Reader[R, A] = Reader(_ => a)
override def flatMap[A,B](st: Reader[R, A])(f: A => Reader[R, B]): Reader[R, B] =
Reader(r => f(st.run(r)).run(r))
}
or more simply:
case class Reader[R, A](run: R => A) {
def map[B](f: A => B): Reader[R, B] =
Reader(r => f(run(r)))
def flatMap[B](f: A => Reader[R, B]): Reader[R, B] =
Reader(r => f(run(r)).run(r))
}
I wonder if there is an intrinsic relationship between Reader Monad and Function1. I have been readying here and there comment hinting at that. Is Reader by definition a Function1 monad ?
I do not think so. But I would like to wrap my head around the concept.
What does it means to sequence function, when those function are of type 1 ?
That is, you take a function and you apply a function that return the same type of function. I do think Reader is a specific technics, independent of the fact that the function are function 1. Threadying the environment through is just a choice, and it could be done with FunctionN if we wanted to.
Just an intuition.
Here is how the exercise comes in FP programming in Scala:
Hard: To cement your understanding of monads,
give a monad instance for the following type,
and explain what it means.
What are its primitive operations?
What is the action of flatMap? ......
case class Reader[R, A](run: R => A)
object Reader {
def readerMonad[R] = new Monad[({type f[x] = Reader[R,x]})#f] {
def unit[A](a: => A): Reader[R,A]
def flatMap[A,B](st: Reader[R,A])(f: A => Reader[R,B]): Reader[R,B]
}
}”
and part of the answer that leave me unsatisfied
// The action of Reader's `flatMap` is to pass the `r` argument along to both the
// outer Reader and also to the result of `f`, the inner Reader. Similar to how
// `State` passes along a state, except that in `Reader` the "state" is read-only.
I understand that as I can read code. I think that explanation falls short to answer clearly the question of the exercise. I was looking for something a bit more general than a bare description of what the code does.
For instance, what does that mean have the type R fixed. What does that means to chain computation that return as effect Function that take the same input parameter type ?
Upvotes: 3
Views: 200
Reputation: 51658
Reader[R, A]
is a wrapper over R => A
(so methods can be defined just inside the class, not as extension methods for functions). A function f
can be wrapped to a reader Reader(f)
, a reader r
can be unwrapped to a function r.run
. So Reader[R, A]
↔ R => A
is an isomorphism.
Reader[R, ?]
has an instance of type class Monad
.
R => ?
has an instance of type class Monad
.
Upvotes: 5