Frage

Ich versuche, eine minimale Form von abhängigen Typen in Scala zu erhalten. Wenn ich habe

class A[T <: Int]

val x: Int = 7

ich kann

val a = new A[x.type]

Jetzt ist es möglich, sich zu erholen x von seinem Singleton x.type?

Oder, wenn das nicht möglich ist, ist es möglich, eine stabile Kennung irgendwie mit einem Typ zu verknüpfen und dann zu extrahieren?

War es hilfreich?

Lösung

Nein, Sie können sich nicht erholen x aus x.type Wegen des JVM -Typs. Wie würde dies zum Beispiel implementiert?

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

Auf der JVM -Bytecode -Ebene gibt es keine Möglichkeit f kann Wert finden x: A gegeben A = x.type Weil es nichts zu arbeiten gibt: Alle Typparameter gehen zur Laufzeit verloren und trotzdem die x Wert ist nicht verfügbar auf fParameterstapel.

Aus dem gleichen Grund müssten Sie es als stabile Art eines Typs erhalten Manifest Wert. Aber als ich es versuchte, bekomme ich ein seltsames Ergebnis,

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

Ich bin mir nicht sicher, warum diese beiden Typen gleich sind-sie haben sogar unterschiedlich toString Darstellungen. Könnte dies ein Scala -Fehler sein? Aktualisieren: Laut dem Scaladoc, Die Typ-Relationsoperatoren <: <und =: = sollten nur als Approximationen betrachtet werden, da es zahlreiche Aspekte der Typ-Konformität gibt, die in Manifests noch nicht angemessen dargestellt werden.

Zusammenfassend lässt sich sagen, dass die Wiedergabe von Typinformationen in Laufzeitwerte nicht automatisch auf dem JVM stattfindet. Scala Manifest soll die Lücke füllen, aber ich denke, es funktioniert nicht mit abhängigen Typen.

Andere Tipps

Um Ihre zweite Frage zu beantworten, "eine stabile Kennung mit einem Typ zu verknüpfen", besteht eine Möglichkeit, dies zu tun, um Typklassen zu verwenden. Nehmen wir an, ich möchte eine String -Beschreibung mit Typen in Verbindung bringen. Ich kann dies wie folgt tun:

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

Um solche Tags wiederherzustellen, geben Sie die implizite Magie ein:

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

Z.B:

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

Sie können nach Bedarf sogar Tags generieren, indem Sie implizite Funktionen verwenden. Zum Beispiel:

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

Ich kann jetzt Folgendes machen:

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

und sogar:

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

Bitte vergib der Pluralisierung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top