Suche…


Einführung in die Programmierung auf Typebene

Wenn wir eine heterogene Liste betrachten, bei der die Elemente der Liste unterschiedliche, aber bekannte Typen haben, kann es wünschenswert sein, Operationen an den Elementen der Liste gemeinsam durchführen zu können, ohne die Typinformationen der Elemente zu verwerfen. Im folgenden Beispiel wird eine Mapping-Operation über eine einfache heterogene Liste implementiert.

Da der Elementtyp variiert, ist die Klasse von Operationen , die wir durchführen kann , um eine Form des Typs Projektion beschränkt, so definieren wir eine trait Projection abstract mit type Apply[A] der Berechnung der Ergebnistyp des Vorsprunges und def apply[A](a: A): Apply[A] den Ergebniswert der Projektion zu berechnen .

trait Projection {
  type Apply[A] // <: Any
  def apply[A](a: A): Apply[A]
}

Bei der Implementierung des type Apply[A] programmieren wir auf der Typebene (im Gegensatz zur Wertebene).

Unser heterogener Listentyp definiert eine map Operation durch den gewünschten Vorsprung parametrisiert sowie die Typ der Projektion. Das Ergebnis der HList ist abstrakt, variiert je nach Implementierung von Klasse und Projektion und muss natürlich immer noch eine HList :

sealed trait HList {
  type Map[P <: Projection] <: HList
  def map[P <: Projection](p: P): Map[P]
}

Im Fall von HNil , der leeren heterogenen Liste, ist das Ergebnis einer Projektion immer selbst. Hier erklären wir das trait HNil als Bequemlichkeit, damit wir HNil anstelle von HNil.type als Typ schreiben HNil.type :

sealed trait HNil extends HList
case object HNil extends HNil {
  type Map[P <: Projection] = HNil
  def map[P <: Projection](p: P): Map[P] = HNil
}

HCons ist die nicht leere heterogene Liste. Hier behaupten wir, dass der resultierende Kopftyp bei Anwendung einer Kartenoperation derjenige ist, der sich aus der Anwendung der Projektion auf den Kopfwert ( P#Apply[H] ) ergibt, und dass der resultierende Schwanztyp derjenige ist, der sich aus der Abbildung des ergibt Projektion über den Schwanz ( T#Map[P] ), der als HList :

case class HCons[H, T <: HList](head: H, tail: T) extends HList {
  type Map[P <: Projection] = HCons[P#Apply[H], T#Map[P]]
  def map[P <: Projection](p: P): Map[P] = HCons(p.apply(head), tail.map(p))
}

Die naheliegendste Projektion ist die Ausführung einer Form der Umhüllung. Das folgende Beispiel führt zu einer Instanz von HCons[Option[String], HCons[Option[Int], HNil]] :

HCons("1", HCons(2, HNil)).map(new Projection {
  type Apply[A] = Option[A]
  def apply[A](a: A): Apply[A] = Some(a)
})


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow