Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do Scala type lambdas cost of a reflective call?

I'm working with a lot of code with type lambdas at the moment and noticed that IntelliJ is warning me that it's an "Advanced language feature: reflective call".

Sample code:

implicit def monoidApplicative[M](M: Monoid[M]) =
  new Applicative[({ type f[x] = Const[M, x] })#f] {
    def unit[A](a: => A): M = M.zero
    override def apply[A,B](m1: M)(m2: M): M = M.op(m1, m2)
  }

Note: I figure that this could be a bug the IntelliJ Scala plugin as it would make sense that type lambdas are resolved at compile time.

like image 702
Steven Shaw Avatar asked May 10 '16 09:05

Steven Shaw


1 Answers

IDEA just gets confused because of the { } block. None of this code even exists at runtime.

Here is a small example. A generic identity method for types with one type argument:

def id[F[_], A](value: F[A]) = value

It is not possible to call this method with a type that takes two type arguments:

class Test[A, B]
id(new Test[Int, Int])

<console>:10: error: type mismatch;
 found   : Test[Int,Int]
 required: F[A]
              id(new Test[Int, Int])

But we can use a type lambda to define a function id2 that is implemented in terms of id:

def id2[F[_, _], A, B](value: F[A, B]) =
  id[({ type f[x] = F[A, x] })#f, B](value)

id2(new Test[Int, Int])
res3: Test[Int,Int] = Test@1a53ac0c

Quite convoluted, but it works. Now let's look at the bytecode.

scala> :javap -c id2

...

  public <F, A, B> F id2(F);
Code:
   0: getstatic     #19                 // Field .MODULE$:L;
   3: aload_1
   4: invokevirtual #22                 // Method .id:(Ljava/lang/Object;)Ljava/lang/Object;
   7: areturn

...

As you can see, there is nothing left of all the type trickery. No reflection, nothing. Just java.lang.Object.

like image 154
Rüdiger Klaehn Avatar answered Jan 19 '23 16:01

Rüdiger Klaehn