目次
ScalaのAuxパターン
Kazuki Moriyama (森山 和樹)
ScalaにはAuxパターンというものがあるらしいのでまとめ。
解決したい課題
ある型に対しての型クラスインスタンスが複数欲しいときがあり、しかもその型クラス同士に依存関係があるとする。
trait TypeClass[T] {
type R
}
def something[T](implicit tc: TypeClass[T], Monad[tc.R]): tc.R
上の例でいくとsomethingメソッドはTのTypeClassインスタンスが必要だ。
しかもTypeClass[T]がもつRをdependent typeで解決してそのRに対してのMonadインスタンスが必要である。
しかしこれはコンパイルが通らない。
なぜかと言うとScalaでは同じパラメタブロックに対してのdependent typeを許していない。
これを解決するのがAuxパターン。
Auxパターンの使い方
上の例に追加でtype aliasを追加し、somethingのメソッドシグネチャを少し変更する。
trait TypeClass[T] {
type R
}
object TypeClass {
type Aux[T0, R0] = TypeClass[T0] { type R = R0 }
}
def something[T, R](implicit tc: TypeClass.Aux[T, R], Monad[R]): R
つまりどういうことかと言うと今までTypeClass内にいたRを型パラメタとして表に引っ張り出してきたのだ。
これによってdependent typeを使わずとも型クラスインスタンス同士の関係性が表現できる。
また少し混乱するがシグネチャにある通り TypeClass.Aux[T, RR] == TypeClass[T] { type R = RR }
である。
なので変更前と必要となる型クラスのインスタンスは変わっていない。
ちなみにこの問題はdottyで解決される。
参考