Recherche…


Introduction à la programmation au niveau du type

Si nous considérons une liste hétérogène, dans laquelle les éléments de la liste ont des types variés mais connus, il peut être souhaitable de pouvoir effectuer des opérations sur les éléments de la liste collectivement sans ignorer les informations de type des éléments. L'exemple suivant implémente une opération de mappage sur une liste hétérogène simple.

Comme le type d'élément varie, la classe d'opérations que nous pouvons effectuer est restreinte à une forme de projection de type. Nous définissons donc un trait Projection type Apply[A] abstrait type Apply[A] calculant le type de résultat de la projection et def apply[A](a: A): Apply[A] calculant la valeur de résultat de la projection.

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

En implémentant le type Apply[A] nous programmons au niveau du type (par opposition au niveau de la valeur).

Notre type de liste hétérogène définit une opération de map paramétrée par la projection souhaitée ainsi que par le type de projection. Le résultat de l'opération de carte est abstrait, variera selon la classe et la projection, et doit toujours être une liste HList :

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

Dans le cas de HNil , la liste hétérogène vide, le résultat de toute projection sera toujours lui-même. Ici, nous déclarons le trait HNil comme une commodité afin que nous puissions écrire HNil comme un type au lieu de 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 sont la liste hétérogène non vide. Ici, nous affirmons que lorsqu’on applique une opération de carte, le type de tête résultant est celui qui résulte de l’application de la projection à la valeur de tête ( P#Apply[H] ) et que le type de queue résultant projection sur la queue ( T#Map[P] ), connue pour être une 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))
}

La projection la plus évidente consiste à exécuter une opération d’emballage - l’exemple suivant fournit une instance de 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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow