Scala lists with existential types: `map {case t => ...}` works, `map {t => ...}` does not?

Suppose we define an existential type:

type T = (X => X, X) forSome { type X }

and then defined a list of types List[T]:

val list = List[T](
  ((x: Int) => x * x, 42),
  ((_: String).toUpperCase, "foo")
)

It is well known [ 1 ], [ 2 ] that the following attempt mapdoes not work before :

list.map{ x => x._1(x._2) }

But then why the following work ?:

list.map{ case x => x._1(x._2) }

Note that the answers to both related questions assume that a type variable is required in the template mapping, but it also works without a type variable. The focus of the question is more on why it works { case x => ... }?

+4
source share
1 answer

( , , , , .)


,

list.map{ x => x._1(x._2) }
list.map{ case x => x._1(x._2) }

list map f1
list map f2

val f1: T => Any = t => t._1(t._2)
val f2: T => Any = _ match {
  case q => q._1(q._2)
}

, f1 , f2 .

, f1 :

  • t (X => X, X) forSome { type X }
  • , t._1 (X => X) forSome { type X }.
  • , t._2 X forSome { type X }, Any.
  • (X => X) forSome { type X } Any, (SuperSpecialType => SuperSpecialType) SuperSpecialType.

, f1 , .


, f2 , typechecker. someFile.scala:

class O {
  type T = (X => X, X) forSome { type X }

  def f2: T => Any = t => t match {
    case q => q._1(q._2)
  }

  def f2_explicit_func_arg: T => Any = t => t match {
    case q => {
      val f = q._1
      val x = q._2
      f(x)
    }
  }
}

typechecker

$ scalac -Xprint:typer someFile.scala 

( ):

class O extends scala.AnyRef {
  type T = (X => X, X) forSome { type X };
  def f2: O.this.T => Any = ((t: O.this.T) => t match {
    case (q @ _) => q._1.apply(q._2)
  });
  def f2_explicit_func_arg: O.this.T => Any = ((t: O.this.T) => t match {
    case (q @ _) => {
      val f: X => X = q._1;
      val x: X = q._2;
      f.apply(x)
    }
  })
}

f2_explicit_func_arg ( f2) , f2 -. desugared type-checked f2_explicit_func_arg , X , typechecker :

f: X => X
x: X

f(x) .


, .

:

type TypeCons[X] = (X => X, X)
list.map{ case t: TypeCons[x] => t._1(t._2) }

:

list.map{ case t: TypeCons[x] => {
  val func: x => x = t._1
  val arg: x = t._2
  func(arg)
}}

, f2.

+1

Source: https://habr.com/ru/post/1695918/


All Articles