Scala Language
タイプレベルプログラミング
サーチ…
タイプレベルプログラミング入門
リストの要素が多様であるが既知の型を持つ異種のリストを考えると、要素の型情報を破棄することなくリストの要素に対して一括して操作を実行できることが望ましいかもしれない。次の例では、単純な異種リストに対してマッピング操作を実装しています。
要素型が変化するため、実行できる操作の種類は何らかの形の投影に限定されているので、特性を定義する。抽象的な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)
})