user1484819 user1484819 - 28 days ago 5x
Scala Question

scala implicit method argument eliminate ambiguity

I don't quite understand following code:

object M {
implicit object AMarker
implicit object BMarker

def m(ints: Seq[Int])(implicit i: AMarker.type ): Unit = {
println(s"int seq $ints");

def m(strs: Seq[String])(implicit s: BMarker.type ): Unit = {
println(s"string seq $strs")

import M._

m(Seq(1, 2, 3))
m(Seq("a", "b", "c"))

If it weren't for the two markers, it will not compile because the two
methods have the same signature after type erasure.

However, I don't understand what is the "magic" that links
to a
, and

More specificly, when I call
m(Seq("a", "b"))
, how does the compiler know it should use the implicit
, and call the second
? Hasn't the
already been type erased?


To answer your question directly, no, the type erasure hasn't happened yet. Implicit search has to happen with full knowledge of types. To see how these methods look at runtime, you can run javap to see the compiled classes:

scala> :javap M -s
Compiled from "<console>"
public class M$ {
  public static final M$ MODULE$;
    Signature: LM$;
  public static {};
    Signature: ()V

  public void m(scala.collection.Seq<java.lang.Object>, M$AMarker$);
    Signature: (Lscala/collection/Seq;LM$AMarker$;)V

  public void m(scala.collection.Seq<java.lang.String>, M$BMarker$);
    Signature: (Lscala/collection/Seq;LM$BMarker$;)V

  public M$();
    Signature: ()V

So basically the compiler has made unambiguous runtime methods. It looks up the exact method during compile time, and essentially uses the implicit object to disambiguate.

Cool trick BTW! I haven't seen it used directly this way before.