Scala Language
Programmering op type niveau
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)
})