Zoeken…


Inleiding tot programmering op type niveau

Als we een heterogene lijst beschouwen, waarin de elementen van de lijst verschillende maar bekende typen hebben, kan het wenselijk zijn om bewerkingen op de elementen van de lijst collectief te kunnen uitvoeren zonder de type-informatie van de elementen te negeren. Het volgende voorbeeld implementeert een toewijzingsbewerking via een eenvoudige heterogene lijst.

Omdat het elementtype varieert, is de klasse van operaties die we kunnen uitvoeren beperkt tot een bepaalde vorm van projectietype, dus een eigenschap definiëren Projection met abstracte type Apply[A] het berekenen van het resultaattype van het uitsteeksel en def apply[A](a: A): Apply[A] berekenen van de resultaatwaarde van het uitsteeksel.

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

Bij het implementeren van type Apply[A] programmeren we op het type niveau (in tegenstelling tot het waardeniveau).

Ons heterogene lijsttype definieert een map wordt geparametriseerd door de gewenste projectie en het type van de projectie. Het resultaat van de HList is abstract, varieert per implementatieklasse en projectie en moet natuurlijk nog steeds een HList :

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

In het geval van HNil , de lege heterogene lijst, is het resultaat van een projectie altijd zichzelf. Hier verklaren we trait HNil voor het gemak, zodat we HNil kunnen schrijven als een type in plaats van 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 is de niet-lege heterogene lijst. Hier stellen we dat bij het toepassen van een kaartbewerking het resulterende koptype dat is dat resulteert uit de toepassing van de projectie op de kopwaarde ( P#Apply[H] ), en dat het resulterende staarttype dat is wat resulteert uit het in kaart brengen van de projectie over de staart ( T#Map[P] ), bekend als een 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))
}

De meest voor de hand liggende dergelijke projectie is om een vorm van HCons[Option[String], HCons[Option[Int], HNil]] te voeren - het volgende voorbeeld levert een instantie van 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow