Diferencia entre la inferencia de tipos de parámetros de método y tipo de clase en la coincidencia de patrones

Mario Galic:

¿Por qué patrón de trabajo correspondiente al parámetro de tipo diferente proviene de un método que encierra en contraposición a una clase envolvente? Por ejemplo,

trait Base[T]
case class Derived(v: Int) extends Base[Int]

class Test[A] {
  def method(arg: Base[A]) = {
    arg match {
      case Derived(_) => 42
    }
  }
}

da error

constructor cannot be instantiated to expected type;
 found   : A$A87.this.Derived
 required: A$A87.this.Base[A]
      case Derived(_) => 42
           ^

mientras que compila con éxito cuando Aes parámetro de tipo de método

class Test {
  def method[A](arg: Base[A]) = {
    arg match {
      case Derived(_) => 42
    }
  }
}

La pregunta se basa en la de Daniel análisis , que he usado para tratar de proporcionar respuesta a la pregunta similar.

fusiones:

Yo no tengo el 100% de respuesta completa, pero tengo un puntero que podría ser suficiente para usted.

Ofertas compilador Scala con GADTs (Tipos Generalizado algebraica de datos) de una manera muy particular. Algunos casos se resuelven con tratamiento especial, algunos casos no han sido resueltos. Dotty está tratando de llenar la mayor parte de los agujeros, y que ya ha resuelto muchos de los problemas relacionados, sin embargo, todavía hay bastantes abiertos queridos, así.

Un ejemplo típico de un manejo especial GADT en Scala 2 compilador está muy relacionado con su caso de uso. Si echamos un vistazo a:

def method[A](arg: Base[A]) = {
  arg match {
    case Derived(_) => 42
  }
}

y declaramos explícitamente el tipo de retorno que ser A:

def method[A](arg: Base[A]): A 

se compilará bien. El IDE podría quejarse, pero el compilador le permitirá llevarlo a cabo. Método dice que devuelve una A, pero el caso evalúa coincidencia de patrones en una Int, que en teoría no debería compilar. Sin embargo, un manejo especial de GADTs en el compilador dice que está bien, porque en esa rama de la coincidencia de patrones particular, Aha sido "fijo" para ser un Int(porque emparejado en el Derivedque es una Base[Int]).

Parámetro de tipo genérico para el GADT (en nuestro caso A) tiene que ser declarado en alguna parte. Y aquí está la parte interesante - el manejo de compilador especial sólo funciona cuando se declara como el parámetro de tipo del método de cerramiento . Si está viniendo de un miembro de tipo o un parámetro de tipo de la envolvente rasgo / clase, no compila, a medida que fue testigo de uno mismo.

Es por esto que he dicho que no es una respuesta completa al 100% - No puedo señalar a un lugar concreto (como especificación oficial), que documenta esta correctamente. Fuentes en el manejo de GADTs en Scala descendido a un par de entradas del blog , que son grandes por cierto, pero si quieres más de que va a tener que excavar en el código de compilador de sí mismo. He intentado hacer exactamente eso, y creo que todo se reduce a este método , pero si realmente quiere ir más profundo, puede que desee para hacer ping a alguien con más experiencia con el código base compilador de Scala.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=369213&siteId=1
Recomendado
Clasificación