Pregunta

Estoy tratando de obtener una forma mínima de tipos dependientes en Scala. Si tengo

class A[T <: Int]

val x: Int = 7

puedo

val a = new A[x.type]

Ahora es posible recuperar x de su singleton x.type?

O, si eso no es posible, ¿es posible asociar un identificador estable con un tipo de alguna manera y luego extraerlo?

¿Fue útil?

Solución

No, no puedes recuperarte x de x.type Debido a la borrado tipo JVM. Por ejemplo, ¿cómo se implementaría esto?

def f[A]: A = ???
f[x.type]

En el nivel de código de bytecodo JVM, no hay forma de que f puede encontrar valor x: A dado A = x.type Porque no tiene nada con lo que trabajar: todos los parámetros de tipo se pierden en el tiempo de ejecución, y de todos modos, el x El valor no está disponible en fPila de parámetros.

Por la misma razón, para obtener un tipo estable de tipo, tendría que reificarlo como un Manifest valor. Pero cuando lo intenté, obtengo un resultado extraño,

def f[A : Manifest] = implicitly[Manifest[A]]
val x = "hi"
val y = "ho"
println(f[x.type]) // hi.type
println(f[y.type]) // ho.type
f[x.type] == f[y.type] // true !?

No estoy seguro de por qué estos dos manifiestos de tipo son iguales, incluso tienen diferentes toString representaciones. ¿Podría ser este un error de Scala? Actualizar: De acuerdo con la Scaladoc, Los operadores de relación de tipo <: <y =: = deben considerarse aproximaciones solo, ya que existen numerosos aspectos de conformidad de tipo que aún no se representan adecuadamente en los manifiestos.

Para resumir, la reificación de la información de tipo en valores de tiempo de ejecución no ocurre automáticamente en el JVM. Scala Manifest Se supone que llena el vacío, pero supongo que no funciona con tipos dependientes.

Otros consejos

Para responder a su segunda pregunta, "asociar un identificador estable a un tipo", una forma de hacerlo es usar clases de tipo. Digamos que quiero asociar una descripción de una cadena a los tipos, puedo hacerlo de la siguiente manera:

trait Tag[A] {
  val desc : String
}

implicit object StringTag extends Tag[String] {
  val desc = "character string"
}

implicit object IntTag extends Tag[Int] {
  val desc = "32-bit integer"
}

Ahora, para recuperar tales etiquetas, ingrese la magia implícita:

def printTag[T : Tag] {
  val tag = implicitly[Tag[T]]
  println("Type is described as : " + tag.desc)
}

P.ej:

printTag[String] // prints "Type is described as : character string"
printTag[Double] // compile-time error: no implicit value found of type Tag[Double]

Incluso puede generar etiquetas según sea necesario, utilizando funciones implícitas. Por ejemplo:

implicit def liftTagToList[T : Tag] = new Tag[List[T]] {
  val underlying = implicitly[Tag[T]].desc
  val desc = "list of " + underlying + "s"
}

Ahora puedo hacer lo siguiente:

// prints "Type is described as : list of character strings"
printTag[List[String]]

E incluso:

// prints "Type is described as : list of list of character stringss"
printTag[List[List[String]]]

Por favor, perdona la pluralización.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top