flatten is defined as:
override def flatten[B](implicit toIterableOnce: A => IterableOnce[B])
My code is:
val myList = List(1,2,3)
println(myList.map(x => List(x, 2*x)).flatten)
So if I understand it correctly, when I call flatten I need an implicit function defined somewhere and this function takes List[Int] as input and returns IterableOnce[Int].
I haven't defined any such function and code works fine, so implicit is found somewhere. How can I find where its exactly defined? I was expecting it in Predef, but seems its not there.
CodePudding user response:
If you do
// libraryDependencies = scalaOrganization.value % "scala-reflect" % scalaVersion.value
import scala.reflect.runtime.universe.reify
println(reify{ myList.map(x => List(x, 2*x)).flatten }.tree)
you'll see
App.this.myList.map(((x) => `package`.List.apply(x, 2.$times(x)))).flatten(Predef.$conforms)
so implicit toIterableOnce: A => IterableOnce[B]
is Predef.$conforms
(you were right, it's in Predef
)
https://github.com/scala/scala/blob/2.13.x/src/library/scala/Predef.scala#L510
/** An implicit of type `A => A` is available for all `A` because it can always
* be implemented using the identity function. This also means that an
* implicit of type `A => B` is always available when `A <: B`, because
* `(A => A) <: (A => B)`.
*/
// $ to avoid accidental shadowing (e.g. scala/bug#7788)
implicit def $conforms[A]: A => A = <:<.refl
Indeed, List[Int] <: IterableOnce[Int]
implicitly[List[Int] <:< IterableOnce[Int]] // compiles
implicitly[List[Int] => IterableOnce[Int]] // compiles
It's useful to know how to debug implicits:
In scala 2 or 3, is it possible to debug implicit resolution process in runtime?
CodePudding user response:
FWIW, if using Scala 2, you can also run your program with the -Xprint:typer
flag using either scala
or scalac
, and you'll see all the implicits the compiler inserts in your program:
println(myList.map(x => List(x, 2*x)).flatten)
Gets translated into:
scala.Predef.println(Main.this.myList.map[List[Int]](((x: Int) =>
scala.`package`.List.apply[Int](x, 2.*(x))))
.flatten[Any](scala.Predef.$conforms[List[Int]]))