2017-02-25 7 views
1

私はScalaで(path-)依存型を使用していて、次のような場合にはうまく解決できませんでした。 依存型の階層をいくつか持たせたいとし、それぞれに "所有者"オブジェクトへの参照を戻したいとします。私はこのバックリファレンスが正しい「所有者」オブジェクトのいくつかのメソッドを呼び出せるようにしたい。それを行う正しい方法は何ですか?リファレンスバック付き依存型(Scala)

ここに小さな例があります。依存型がInnerの「基本」形質Outerがあります。ベースOuterの特性は、従属型で機能するいくつかのメソッドdoubleを定義します。特定の従属クラスConcreteInnerを持つ特定のクラスConcreteOuterもあり、その値には簡単なIntが使用されています。

trait Outer { 
    outerSelf => 

    trait BaseInner { 
    val outer: outerSelf.type = outerSelf 

    def asDependent: outer.Inner   // #1 
    // def asDependent: outerSelf.Inner // #2 
    } 

    type Inner <: BaseInner 

    def double(inner: Inner): Inner 
} 

class ConcreteOuter extends Outer { 
    case class ConcreteInner(val v: Int) extends BaseInner { 
    override def asDependent = this  
    } 

    type Inner = ConcreteInner 

    def createInner(v: Int): Inner = new ConcreteInner(v) 

    override def double(inner: Inner): Inner = new ConcreteInner(2 * inner.v) 
} 

これまでのところとても良いです。今私はいくつかのInnerクラスのインスタンスしか持っていないが、対応するOuter -instanceのインスタンスがあるコンテキストでそのdoubleメソッドを呼び出すことができると仮定します。たとえば、ちょうど他のいくつかの(独立した)状況で、元Outer.doubleを呼び出し、別のdoubleメソッドを作成してみましょう:

object DepTest extends App { 

    //def double(inner: Outer#Inner) = inner.outer.double(inner)   // #3 

    def double(inner: Outer#Inner) = inner.outer.double(inner.asDependent) // #4 


    val c1 = new ConcreteOuter 
    val i1 = c1.createInner(123) 
    val d1 = double(i1) 
    println(d1) 

} 

このコードはコンパイルされますが、asDependentのかなり醜いハックが必要です。行#4の代わりに行#3を使用すると、コードはコンパイルされません。私はもう

def double(inner: Outer#Inner) = { 
    val outer = inner.outer 
    outer.double(inner.asDependent) 
    } 

コードはコンパイルされません、次のようにライン#3を分割した場合、私はライン#2とライン#1を交換した場合また、さえasDependentハックは動作を停止します。

何とか時には、コンパイラはouterSelf別名Innerオブジェクトおよび「所有者」オブジェクトのouterフィールドが同じものであることを知っていて、時にはそれがないと、時にコンパイラを説得する方法は明らかではないようなので、それが見えますそれらを同じものとして認識しません。

これを回避する方法はありますか?それとも、これは私の問題に対する完全に間違ったアプローチですか? (明らかに現実の世界では、DepTest.doubleなどのダムプロキシだけでなく、multiplyByPow2(val : Outer#Inner, exponent: Int)などの上位レベル関数のライブラリを作成したい)

答えて

0

私はパス依存型ではあまり経験はありませんが、 hereから読み込まれ、何が起こることはOuterouterSelf.typeは同じものではありませんということであるようだ。

  • outerSelf.typeouterSelfまたはnull
  • outerSelf: Outerのみで構成されてのいずれかで構成されてい210

あなたの問題はここから来ていると思いますが、これ以上のことを知るには十分な知識がありません。

関連する問題