Scala2におけるType Lambdaについては、下記のブログエントリが詳しい。
最初に、型パラメータの数を一つとして定義していると、型パラメータを二つ取る物を渡せない。
scala> trait Functor[F[_]] trait Functor scala> type F1 = Functor[Option] type F1 scala> type F2 = Functor[List] type F2 scala> type F3 = Functor[Map] ^ error: Map takes 2 type parameters, expected: 1
Mapが取る二つの型のうち、一つが決まれば、残るは一つなので大丈夫。
scala> type IntKeyMap[A] = Map[Int, A] type IntKeyMap scala> type F3 = Functor[IntKeyMap] type F3
ただし、いちいち途中の階層の型を定義するのは面倒くさい。
そこで、無名の型を定義して、その中で一つの型を確定させ、その型を返す方法が発明された。これなら1行で済むし、余計な命名も不要になる。
scala> type F5 = Functor[({ type T[A] = Map[Int, A] })#T] type F5
でも何をやっているのかわかりづらい。
そこで、Scala3には専用の構文(=>>
)が導入された。だいぶ謎記号が減ったScalaだけど、ここに来て一つ増えた。
scala> type F6 = Functor[ [A] =>> Map[Int, A] ] // defined alias type F6 = Functor[[A] =>> Map[Int, A]]
Scala2の時のtype lambdaの書き方をすると、対応が分かりやすい。
scala> type F7 = Functor[({ type T[A] = Map[Int, A] })#T] // defined alias type F7 = Functor[[A] =>> Map[Int, A]]
型のカリー化もできるそうだ。
type TL = [X] =>> [Y] =>> (X, Y)
型パラメータが得られば、こんな指定もできる。
scala> def foo[A[_,_],B](functor: Functor[({type AB[C] = A[B,C]})#AB]) = ??? def foo[A[_$3, _$4], B](functor: Functor[[C] =>> A[B, C]]): Nothing scala> def foo[A[_,_],B](functor: Functor[ [C] =>> A[B, C]]) = ??? def foo[A[_$1, _$2], B](functor: Functor[[C] =>> A[B, C]]): Nothing
ライブラリを作る人でなければ、このような汎用性のための機能はいらないかもしれないけど。
あと、これらのコードを動かしている最中に、aliasの挙動がよく分からなくなったけど、良い記事を見つけた。