サーチ…


タイプレベルプログラミング入門

リストの要素が多様であるが既知の型を持つ異種のリストを考えると、要素の型情報を破棄することなくリストの要素に対して一括して操作を実行できることが望ましいかもしれない。次の例では、単純な異種リストに対してマッピング操作を実装しています。

要素型が変化するため、実行できる操作の種類は何らかの形の投影に限定されているので、特性を定義する。抽象的なtype Apply[A]を持つProjectionの結果のを計算type Apply[A]def apply[A](a: A): Apply[A]投影の結果を計算するためにdef apply[A](a: A): Apply[A]ます。

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

type Apply[A]実装では、(値レベルではなく)型レベルでプログラミングしています。

私たちの異種リストタイプは、投影のタイプと同様に、所望の投影によってパラメータ化されたmap操作を定義しmap 。マップ操作の結果は抽象クラスであり、クラスと投影を実装することによって異なりますが、当然HListなければなりません。

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

空の異種リストであるHNilの場合、投影の結果は常にそれ自身です。ここでは、宣言しtrait HNil私たちが書くことができるように利便性のHNilする代わりに、タイプとして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は、空でない異種のリストです。ここでは、マップ演算を適用するとき、結果のヘッドタイプは、ヘッド値( P#Apply[H] )への投影のP#Apply[H]から生じるものであり、結果のテールタイプは、 HListであることが知られているテール( T#Map[P] )上の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))
}

そのような投影は、いくつかの形式のラッピング操作を実行することです。次の例は、 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
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow