I'm learning category theory. I understand the concept of reader monad, it's even pretty easy to implement:
case class Reader[DEP, A](g: DEP => A) {
def apply(dep: DEP): A = g(dep)
def map[B](f: A => B): Reader[DEP, B] = Reader(dep => f(apply(dep)))
def flatMap[B](f: A => Reader[DEP, B]): Reader[DEP, B] = Reader(dep => f(apply(dep)) apply dep)
}
However, I have problems implementing it with constraint to some generic Monad interface, i.e
trait Monad[A] {
def pure(a: A): Monad[A]
def map[B](f: A => B): Monad[B]
def flatMap[B](f: A => Monad[B]): Monad[B]
}
let's forgot for a second that there's an applicative or functor and let's just put these 3 methods here.
Now, having this interface I have problems implementing ReaderMonad. map method is pretty straighforward, but what about pure and flatMap? What does it even mean to have pure on Reader? To implement flatMap, I need to have a function from A to Reader[DEP, B], but I have A => Monad[B], thus I'm not possible to access apply.
case class Reader[DEP, A](g: DEP => A) extends Monad[A] {
def apply(dep: DEP): A = g(dep)
override def pure(a: A): Reader[DEP, A] = Reader(_ => a) // what does it even mean in case of Reader
override def map[B](f: (A) => B): Reader[DEP, B] = Reader(dep => f(apply(dep)))
override def flatMap[B](f: (A) => Monad[B]): Reader[DEP, B] = ??? // to implement it, I need f to be (A) => Reader[DEP, B], not (A) => Monad[B]
}
Is it possible to implement it this way in scala? I tried to play around with self bound types, but it didn't work either. I know libraries like scalaz or cats uses typeclasses to implement these types, but this is just for educational purpose.