Reputation: 31526
I have written the following code
case class Foo(i: Int, j:Int)
def do1() : Reader[Foo, String] = Reader(f => s"doing ${f.i}")
def do2() : Reader[Foo, String] = Reader(f => s"doing ${f.j}")
now if I try to compose these into another function
def func() : Reader[Foo, List[String]] = Reader(f =>
for {
m1 <- do1()
m2 <- do2()
} yield List(m1, m2)
}
What I was hoping was that I will do func().run(Foo(10, 20))
and this will give me a list of List("doing 10", "doing 20")
but instead I get a compiler error
type mismatch;
found : cats.data.Kleisli[cats.Id,$sess.cmd1.Foo,List[String]]
required: List[String]
m1 <- do1()
^
Compilation Failed
Upvotes: 1
Views: 611
Reputation: 2723
If you look at what the definition for Reader is in the Cats library, you'll find Reader is just a type alias for Kleisli:
type ReaderT[F[_], A, B] = Kleisli[F, A, B]
val ReaderT = Kleisli
type Reader[A, B] = ReaderT[Id, A, B]
So your for comprehension evaluates to:
Kleisli[Id, Foo, List[String]]
Which is the same type as Reader! Just remove wrapping your comprehension in a reader and it works:
def func(): Reader[Foo, List[String]] = {
for {
m1 <- do1()
m2 <- do2()
} yield List(m1, m2)
}
Upvotes: 5