Knows Not Much
Knows Not Much

Reputation: 31526

value pure is not a member of

I have written this code

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import cats.Applicative
import cats.data.OptionT
import cats.instances.future._
import cats.syntax.applicative._

object PureTest extends App {
   type FutureOption[T] = OptionT[Future, T]
   val x1 = Applicative[FutureOption].pure(1)
   val y1 = 1.pure[FutureOption]
   println(x1)
   println(y1)
   val x2 = Foo(1).pure[FutureOption]
   val y2 = Bar("1").pure[FutureOption]
   println(x2)
   println(y2)
   val z1 = (Foo(1), Bar("1")).pure[FutureOption]
   println(z1)
}
case class Foo(i: Int)
case class Bar(s: String)

This is my build.sbt

name := "PureTest"
version := "1.0"
scalaVersion := "2.11.8"
libraryDependencies ++= Seq(
   "org.typelevel" % "cats-core_2.11" % "0.9.0"
)

This code compiles and works fine.

If I add a line import cats.implicits._ as one of the imports, then I get compilations errors

Error:(16, 14) value pure is not a member of Int
   val x = 1.pure[FutureOption]
Error:(17, 16) value pure is not a member of String
   val y = "1".pure[FutureOption]
Error:(18, 21) value pure is not a member of (Int, String)
   val z = (1, "1").pure[FutureOption]
Error:(19, 32) value pure is not a member of (PureTest.Foo, PureTest.Bar)
   val z1 = (Foo(1), Bar("x")).pure[FutureOption]

Why does importing the implicits._ break the code?

Upvotes: 0

Views: 718

Answers (1)

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27535

If there is ambiguity in implicit conversion/class etc compiler chooses none of them. If pimp-my-library pattern depends on the resolution you will end up with "no such method error".

Let's take a look at cats.implicits (I took the "bytecode" version from my IntelliJ):

package cats
object implicits extends scala.AnyRef with cats.syntax.AllSyntax with cats.instances.AllInstances {
}

Since cats.implicits._ fetch both cats.syntax.all._ and cats.instances.all._, you are fetching cats.syntax.all._ twice (when it comes to functionality - when it comes to code, they live in separate objects, so they are seen as two distinct sets of conversions).

Bottom line is that you are fetching the same conversions twice but through two distinct objects - as a result compiler is confused and cannot use them to provide you the methods you want.

Upvotes: 2

Related Questions