In Scala è possibile recuperare la `Val` a cui si fa riferimento da un tipo singleton?

StackOverflow https://stackoverflow.com/questions/7343163

  •  27-10-2019
  •  | 
  •  

Domanda

Sto cercando di ottenere una forma minima di tipi dipendenti in Scala. Se ho

class A[T <: Int]

val x: Int = 7

io posso

val a = new A[x.type]

Ora è possibile recuperare x Dal suo singleton x.type?

Oppure, se ciò non è possibile, è possibile associare in qualche modo un identificatore stabile a un tipo e poi estrarlo?

È stato utile?

Soluzione

No, non puoi recuperare x da x.type A causa della cancellazione del tipo JVM. Ad esempio, come sarebbe implementato?

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

A livello di bytecode JVM, non c'è modo f può trovare valore x: A dato A = x.type Perché non ha nulla con cui lavorare: tutti i parametri del tipo sono persi in fase di esecuzione e comunque, il x Il valore non è disponibile su fStack dei parametri.

Per lo stesso motivo, per ottenere un ID stabile di un tipo, dovresti reinserire come un Manifest valore. Ma quando ci ho provato, ottengo uno strano risultato,

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 !?

Non sono sicuro del motivo per cui questi due manifesti di tipo sono uguali --- hanno anche diversi toString rappresentazioni. Potrebbe essere un bug Scala? Aggiornare: Secondo il Scaladoc, Gli operatori di relazioni di tipo <: <e =: = dovrebbero essere considerati solo approssimazioni, in quanto vi sono numerosi aspetti della conformità del tipo che non sono ancora adeguatamente rappresentati nei manifesti.

Per riassumere, la reificazione delle informazioni del tipo nei valori di runtime non si verifica automaticamente su JVM. Scala's Manifest dovrebbe colmare il divario, ma immagino che non funzioni con tipi dipendenti.

Altri suggerimenti

Per rispondere alla tua seconda domanda, "associando un identificatore stabile a un tipo", un modo per farlo è usare le classi di tipo. Diciamo che voglio associare una descrizione della stringa ai tipi, posso farlo come segue:

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

Ora, per recuperare tali tag, inserisci la magia implicita:

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

Per esempio:

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

Puoi persino generare tag se necessario, usando funzioni implicite. Per esempio:

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

Ora posso fare quanto segue:

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

e persino:

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

Per favore perdona la pluralizzazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top