12

この質問は、Scalaz を使用しているときに何度か遭遇した Scala の暗黙的な解決システムの制限に関するもので、私にはあまり意味がありません。以下に、問題を Scalaz を使用しないバージョンにまとめましたが、必要に応じて動機に関する詳細情報を提供できれば幸いです。

型コンストラクターに関する何かを目撃する型クラスがいくつかあるとします。

import scala.language.higherKinds

trait Foo[F[_]]
trait Bar[F[_], A]

またFoo、いくつかのインスタンスがある場合、次のインスタンスFもあることがわかっているとします。FooBar[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 でこれを試しました。全体に共分散を追加しても役に立ちません。

明らかな何かが欠けていますか?これを理解するのに役立つ仕様の何か、または同様の問題に関する以前の議論を誰かに教えてもらえますか?

4

1 に答える 1

4

OK、100% 確信があるわけではありませんが、これを可能な限り単純な失敗のケースに減らすことで、ある程度の進歩を遂げることができると思います。ここでは、暗黙的なことは問題ではなく、型エイリアスも問題ではありません。これは失敗するのに十分です:

trait Foo[F[_]]
trait Bar[F[_], A]

def barFoo[F[_]: Foo] = new Foo[({type L[X] = Bar[F, X]})#L] {}

val res1: Foo[({type L[X] = Either[String, X]})#L] = null

val works = barFoo[({type L[X] = Either[String, X]})#L](res1)
val fails = barFoo(res1)

この問題は、Scala が as の型引数を推論できないことにありbarFooます[X]Either[java.lang.String,X]これは、 scalac が部分的に適用された型コンストラクターを推論することを拒否したため (または少なくとも関連しているため)のようです。

(関連する注意事項として、これは Scala が容認できないほど複雑であると見なす型の 1 つの例です)。

于 2013-01-15T05:41:53.620 に答える