Scala类型的lambda是否需要反射调用?

时间:2016-05-10 09:52:32

标签: scala intellij-idea

我现在正在处理很多类型为lambdas的代码,并注意到IntelliJ警告我这是“高级语言功能:反射调用”。

示例代码:

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)
  }

注意:我认为这可能是IntelliJ Scala插件的一个错误,因为在编译时解析类型lambdas会有意义。

1 个答案:

答案 0 :(得分:8)

IDEA因为{ }阻止而感到困惑。这些代码甚至都不存在于运行时。

这是一个小例子。具有一个类型参数的类型的通用标识方法:

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

无法使用带有两个类型参数的类型调用此方法:

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])

但是我们可以使用类型lambda来定义一个用id:

实现的函数id2
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

相当令人费解,但它确实有效。现在让我们看看字节码。

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

...

正如你所看到的,所有类型的诡计都没有留下任何东西。没有反思,没有。只需java.lang.Object