Consider the following example:
case class A()
case class B()
object Conversions {
implicit def aToB(a: A): B = B()
implicit def convert[U, T](seq: Seq[U])(implicit converter: U => T): Seq[T] = {
seq.map(converter)
}
}
object Main {
import Conversions._
def main(args: Array[String]): Unit = {
val sa = Seq(A())
def example(): Seq[B] = sa
}
}
This example won't compile by scala compiler for version 2.11.8. I do compilation with IntelliJ Idea, but actually idea don't produce error on the fly and shows that implicit is used for conversion:
Screenshot from Intellij Idea
To workaround this issue I've used the approach described here:
"Scala: Making implicit conversion A->B work for Option[A] -> Option[B]"
My code started to look as follow:
case class A()
case class B()
object Conversions {
implicit def aToB(a: A): B = B()
trait ContainerFunctor[Container[_]] {
def map[A, B](container: Container[A], f: A => B): Container[B]
}
implicit object SeqFunctor extends ContainerFunctor[Seq] {
override def map[A, B](container: Seq[A], f: (A) => B): Seq[B] = {
Option(container).map(_.map(f)).getOrElse(Seq.empty[B])
}
}
implicit def functorConvert[F[_], A, B](x: F[A])(implicit f: A => B, functor: ContainerFunctor[F]): F[B] = functor.map(x, f)
}
object Main {
import Conversions._
def main(args: Array[String]): Unit = {
val sa = Seq(A())
def example(): Seq[B] = sa
}
}
This code compiles well and works as needed.
My questions are:
Why the first approach fails to compile?
Is this somehow related to type erasure and if yes, how usage of Functor helps with it?
How compiler resolves implicits for both of this cases?