0

問題を歩き回っていて、型射影と抽象型に関する新しい奇妙な問題を発見しました。トランザクションを生成するシステムがあり、ブリッジしたいピア システムがあるとします。以下は私には良さそうです:

trait Txn[S <: Sys[S]] {
  def peer: S#Peer#Tx
  def newID(): S#ID
  def newVar[A](id: S#ID, init: A): S#Var[A]
}
trait Sys[S <: Sys[S]] {
  type Tx <: Txn[S]
  type Peer <: Sys[Peer] // parallel system
  type Var[A]
  type ID
}

そして、直接システムを使用できます:

def directWorks[S <: Sys[S]](implicit tx: S#Tx): Unit = {
  val id = tx.newID()
  val v  = tx.newVar(id, 0)
}

しかしpeer、以下に示すように、どういうわけかトランザクションの方法に欠陥があります。

def indirectDoesnt[S <: Sys[S]](implicit tx: S#Tx): Unit = {
  val p   = tx.peer
  val id  = p.newID()
  val v   = p.newVar(id, 0) // what the **** - id is not compatible??
}

error: type mismatch;
 found   : id.type (with underlying type S#Peer#ID)
 required: _30129.Peer#ID where val _30129: S
          val v   = p.newVar(id, 0)
                             ^

私は賢く、それを回避したかった:

def clever[S <: Sys[S]](implicit tx: S#Tx): Unit = {
  def directWorks[S <: Sys[S]](implicit tx: S#Tx): Unit = {
    val id = tx.newID()
    val v  = tx.newVar(id, 0)
  }
  directWorks(tx.peer)
}

...しかし、それも失敗し、何が問題なのかについての手がかりが得られます。

error: inferred type arguments [S#Peer] do not conform to method
       directWorks's type parameter bounds [S <: Sys[S]]
          directWorks(tx.peer)
          ^

それはすべてdef peer: S#Peer#Tx、問題を引き起こすか、(より可能性が高い?)型パラメーターとしてではなく型メンバーtype Peer <: Sys[Peer]として使用すると問題になることを示唆しています。

4

1 に答える 1

0

これで、ほぼ受け入れられる解決策が得られました。の表現型を「固定」するという考えに基づいていSysます。具体的なシステムSでは、常にS#S#Tx == S#Txetc があります。このソリューションについての私の理解では、分散の責任が使用場所からシステム自体に移ります。

これにはいくつかの儀式が含まれているため、この儀式の削除または削減に関する追加の回答に非常に感謝しています。なぜこれが機能するのか、への呼び出しを省略するとfix機能しないのかについての説明も含まれています。

trait VarLike[ -Tx, A ] { def update( value: A )( implicit tx: Tx ) : Unit }

trait Sys[ S <: Sys[ S ]] {
   type Tx       <: Txn[ S ]
   type Var[ A ] <: VarLike[ S#Tx, A ]
   type ID
   type Peer     <: Sys[ Peer ]

   // 'pop' the representation type ?!
   def fix[ A ]( v: S#Peer#Var[ A ]) : Peer#Var[ A ]
   def peer( tx: S#Tx ) : Peer#Tx
}

trait Txn[ S <: Sys[ S ]] {
   def newID() : S#ID
   def newVar[ A ]( id: S#ID, init: A ) : S#Var[ A ]
   def system: S
}

次に 2 つのシステム例を示します。初め:

class InMemTx( val system: InMem ) extends Txn[ InMem ] {
   def newID() {}
   def newVar[ A ]( id: InMem#ID, init: A ) : InMem#Var[ A ] =
      new VarLike[ InMemTx, A ] {
         def update( v: A )( implicit tx: InMemTx ) {}
      }
}
class InMem extends Sys[ InMem ] {
   type Tx       = InMemTx
   type Var[ A ] = VarLike[ Tx, A ]
   type ID       = Unit
   type Peer     = InMem  // reflect back to ourself

   def fix[ A ]( v: Var[ A ]) : Var[ A ] = v
   def peer( tx: Tx ) : Tx = tx
}

2番:

class DurableTx( val system: Durable, val peer: InMem#Tx ) extends Txn[ Durable ] {
   def newID() = 33
   def newVar[ A ]( id: Durable#ID, init: A ) : Durable#Var[ A ] =
      new VarLike[ DurableTx, A ] {
        def update( v: A )( implicit tx: DurableTx ) {}
      }
}
class Durable extends Sys[ Durable ] {
   type Tx       = DurableTx
   type Var[ A ] = VarLike[ Tx, A ]
   type ID       = Int
   type Peer     = InMem

   def fix[ A ]( v: InMem#Var[ A ]) : InMem#Var[ A ] = v
   def peer( tx: Tx ) : InMem#Tx = tx.peer
}

および使用サイトでの検証:

// let's make sure we can use the system as intended
trait TestTrait[ S <: Sys[ S ]] {
   def v : S#Peer#Var[ Int ]

   def test( implicit tx: S#Tx ) {
      val s          = tx.system
      implicit val p = s.peer( tx )
      val vf         = s.fix( v ) // not cool...
      vf()            = 1
   }
}

// see if we can actually create variables
class TestImpl[ S <: Sys[ S ]]( implicit tx: S#Tx ) extends TestTrait[ S ] {
   val v = {
      val s          = tx.system
      implicit val p = s.peer( tx )
      val id         = p.newID()
      p.newVar( id, 0 )
   }
}
于 2012-09-25T22:17:32.457 に答える