この質問は、Scalaz を使用しているときに何度か遭遇した Scala の暗黙的な解決システムの制限に関するもので、私にはあまり意味がありません。以下に、問題を Scalaz を使用しないバージョンにまとめましたが、必要に応じて動機に関する詳細情報を提供できれば幸いです。
型コンストラクターに関する何かを目撃する型クラスがいくつかあるとします。
import scala.language.higherKinds
trait Foo[F[_]]
trait Bar[F[_], A]
またFoo
、いくつかのインスタンスがある場合、次のインスタンスF
もあることがわかっているとします。Foo
Bar[F, _]
implicit def barFoo[F[_]: Foo] = new Foo[({type L[X] = Bar[F, X]})#L] {}
List
と の右側のインスタンスもありますEither
。
implicit object listFoo extends Foo[List]
implicit def eitherFoo[A] = new Foo[({type L[X] = Either[A, X]})#L] {}
これで、次のように記述できるはずであることは明らかです。
type BarList[X] = Bar[List, X]
implicitly[Foo[BarList]]
または、同等に:
implicitly[Foo[({type L[X] = Bar[List, X]})#L]]
実際、どちらも期待どおりに機能します。
だから私は次のことを試します:
type StringOr[X] = Either[String, X]
type BarStringOr[X] = Bar[StringOr, X]
その後:
scala> implicitly[Foo[BarStringOr]]
res2: Foo[BarStringOr] = $anon$1@39a6c855
繰り返しますが、ここで驚くことはありません。しかし、私は試します:
implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]]
そして、私は次のようになります:
<console>:15: error: could not find implicit value for parameter e: Foo[[X]Bar[[X]scala.util.Either[String,X],X]]
implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]]
^
Foo
に必要なインスタンスを推測したり、目的のインスタンスを取得するために明示的にStringOr
呼び出したりすることに問題はありません。barFoo
scala> implicitly[Foo[StringOr]]
res4: Foo[StringOr] = $anon$1@3eaac006
scala> barFoo[StringOr]
res5: Foo[[X]Bar[StringOr,X]] = $anon$1@179fbfea
タイプラムダバージョンが前者では機能するが後者では機能しない場合List
との間にどのような重要な違いがあるかを特定するのに苦労しています。StringOr
Scala 2.10.0-RC5 および 2.9.2 でこれを試しました。全体に共分散を追加しても役に立ちません。
明らかな何かが欠けていますか?これを理解するのに役立つ仕様の何か、または同様の問題に関する以前の議論を誰かに教えてもらえますか?