2012-12-21 10 views
12

この質問はScalaの暗黙の解決システムの制限についてのもので、私がScalazを使用するときに数回実行したものであり、それは私にはあまり意味がありません。私は以下のScalaz-lessバージョンに問題を掘り下げましたが、必要に応じて動機付けに関する詳細情報を提供しています。タイプエイリアスとタイプlambdaの区別

は、私はその証人型コンストラクタについて何かを型クラスのカップルを持っていると仮定します。

import scala.language.higherKinds 

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

今も私はいくつかFためFooインスタンスを持っている場合、私はまたのためにFooインスタンスを持って知っていると仮定しますBar[F, _]

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

私はListEitherの右側のインスタンスをも持っている:

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] = [email protected] 

、ここには驚き。しかし、私は試してみてください。

implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]] 

そして、私は、次を得る:私は目的のインスタンスを取得するには何の問題StringOrのために必要なFooインスタンスを推論する、または明示的にbarFooを呼び出しを持っていない

<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]] 
         ^

注:

scala> implicitly[Foo[StringOr]] 
res4: Foo[StringOr] = [email protected] 

scala> barFoo[StringOr] 
res5: Foo[[X]Bar[StringOr,X]] = [email protected] 

の重要な違いを特定することができませんとStringOrのケースでは、ラムダ型のバージョンは前者では動作しますが後者では動作しません。

私はScala 2.10.0-RC5と2.9.2でこれを試しました。全体に共分散を加えることは役に立たない。

明らかなものがありませんか?誰かが私にこのことを理解させるのに役立つ仕様や、これまでの同様の問題の議論に私を指摘できますか?

+0

このトピックについてはわかりませんが、https://issues.scala-lang.org/browse/SI-2712との関係があります。 – aemxdp

+0

@andriyp:ありがとうございます。私はそれがどのように関連しているのか確かめています –

+0

トラビスはhttps://issues.scala-lang.org/browse/SI-6895でもチケットを開設しました –

答えて

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) 

問題が[X]Either[java.lang.String,X]としてbarFooための型引数を推論するためにScalaのinabalityするissems。これはscalac's refusal to infer a partially applied type constructorに起因する(または少なくとも関連する)ようです。

(これは、Scalaが受け入れがたい複雑なものであると考えられるタイプの1つの例です)。

関連する問題