Sök…


Introduktion till typnivåprogrammering

Om vi betraktar en heterogen lista, där elementen i listan har olika men kända typer, kan det vara önskvärt att kunna utföra operationer på listans element kollektivt utan att kassera elementens typinformation. Följande exempel implementerar en mappningsoperation över en enkel heterogen lista.

Eftersom elementtypen varierar, är den klass av operationer vi kan utföra begränsad till någon form av typ projektion, så vi definierar en egenskap Projection med abstrakt type Apply[A] att beräkna resultattypen hos utsprånget, och def apply[A](a: A): Apply[A] beräkna resultatvärdet av utsprånget.

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

Vid implementering av type Apply[A] programmerar vi på typnivå (i motsats till värdenivån).

Vår heterogena listtyp definierar en map operation parametriseras av den önskade projektionen liksom projektion typ. Resultatet av kartoperationen är abstrakt, kommer att variera genom att implementera klass och projektion och måste naturligtvis fortfarande vara en HList :

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

När det gäller HNil , den tomma heterogena listan, kommer resultatet av alla projektioner alltid att vara sig själv. Här förklarar vi trait HNil som en bekvämlighet så att vi kan skriva HNil som en typ i stället för 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 är den icke-tomma heterogena listan. Här hävdar vi att vid tillämpning av en kartoperation är den resulterande huvudtypen den som är resultatet av tillämpningen av projektionen på huvudvärdet ( P#Apply[H] ), och att den resulterande svanstypen är den som är resultatet av kartläggning av projektion över svansen ( T#Map[P] ), som är känd för att vara en 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))
}

Det mest uppenbara sådana projektet är att utföra någon form av lindningsoperation - följande exempel ger en instans av 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow