Michael
Michael

Reputation: 42050

Applicative instance for Reader monad

I thought that every monad in scalaz had also an Applicative instance. For example, I can use ApplicativeBuilder for Option like this:

scala> (1.some |@| 2.some) {_ + _}
res1: Option[Int] = Some(3)

Now I'd like to do the same with Reader:

scala> type IntReader[A] = Reader[Int, A]
defined type alias IntReader

scala> val r1: IntReader[Int] = Reader {x: Int => x + 1 }
r1: IntReader[Int] = Reader(<function1>)

scala> val r2: IntReader[Int] = Reader {x: Int => x + 2 }
r2: IntReader[Int] = Reader(<function1>)

scala> (r1 |@| r2) {_ + _}
<console>:64: error: value |@| is not a member of IntReader[Int]
          (r1 |@| r2) {_ + _}

Why doesn't this code above compile ?

Upvotes: 1

Views: 186

Answers (1)

Travis Brown
Travis Brown

Reputation: 139038

For the sake of completeness: the Applicative instance is available with no imports:

scala> type IntReader[A] = scalaz.Reader[Int, A]
defined type alias IntReader

scala> scalaz.Applicative[IntReader]
res0: scalaz.Applicative[IntReader] = scalaz.KleisliInstances3$$anon$3@f979171

But if you want to use the |@| syntax you'll need to import scalaz.syntax.apply._:

scala> import scalaz.syntax.apply._
import scalaz.syntax.apply._

scala> val r1: IntReader[Int] = scalaz.Reader((x: Int) => x + 1)
r1: IntReader[Int] = Kleisli(<function1>)

scala> val r2: IntReader[Int] = scalaz.Reader((x: Int) => x + 2)
r2: IntReader[Int] = Kleisli(<function1>)

scala> (r1 |@| r2) { _ + _ }
res1: IntReader[Int] = Kleisli(<function1>)

This is because |@| isn't a method on Reader—it's provided by an ApplyOps enrichment class.

Upvotes: 1

Related Questions