私は Scala を初めて使用します。型境界を使用して、次のコードでコードの重複を回避しようとしています (無関係なものは削除されています)。
trait StandardStep1[-I1] {
def next_step(i:I1):StandardStep2
}
trait StandardStep2
trait UniqueStep1[-I1] extends StandardStep1[I1] {
def next_step(i:I1):UniqueStep2
}
trait UniqueStep2 extends StandardStep2
class DoubleStandardStep1[-IL,-IR](left:StandardStep1[IL], right:StandardStep1[IR]) extends StandardStep1[(IL,IR)] {
def next_step(i:(IL,IR)) = {
val (i_left, i_right) = i
val new_left = left.next_step(i_left)
val new_right = right.next_step(i_right)
new DoubleStandardStep2(new_left, new_right)
}
}
class DoubleStandardStep2(left:StandardStep2, right:StandardStep2) extends StandardStep2
class DoubleUniqueStep1[-IL,-IR](left:UniqueStep1[IL], right:UniqueStep1[IR]) extends UniqueStep1[(IL,IR)] {
def next_step(i:(IL,IR)) = {
val (i_left, i_right) = i
val new_left = left.next_step(i_left)
val new_right = right.next_step(i_right)
new DoubleUniqueStep2(new_left, new_right)
}
}
class DoubleUniqueStep2(left:UniqueStep2, right:UniqueStep2) extends UniqueStep2
説明:
StandardStep1
あるステート マシンのステップを表し、与えられた入力に対してnext_step
を与える操作があります。StandardStep2
UniqueStep1
は、呼び出されたときにStandardStep1
を与える特別なタイプであり、明らかにそのために継承する必要があります。UniqueStep2
next_step
UniqueStep2
StandardStep2
ここで、DoubleStepラッパーを作成する必要がありました。sDoubleStandardStep1
もラップし、呼び出されたときにStandardStep1
a を返します。
同じことを行いますが、 を返します。DoubleStandardStep2
next_step
DoubleUniqueStep1
DoubleUniqueStep2
*DoubleStep* の実装にはnext_step
明らかなコードの重複があります。入力を分割しi_left
、i_right
ラップされnext_step
たステップを同じ方法で呼び出します。
コードのこの部分を実行する一般的な抽象DoubleStep1を作成することにより、このコードの重複を排除する方法を考えました。
object DoubleStepHelper {
def next_step_args[IL,IR,SL <: StandardStep1[IL],SR <: StandardStep1[IR]](left:SL,right:SR)(i:(IL,IR)) = {
val (i_left, i_right) = i
val new_left = left.next_step(i_left)
val new_right = right.next_step(i_right)
(new_left, new_right)
}
}
class DoubleStandardStep1[-IL,-IR](left:StandardStep1[IL], right:StandardStep1[IR]) extends StandardStep1[(IL,IR)] {
def next_step(i:(IL,IR)) = {
((l,r) => new DoubleStandardStep2(l,r)).tupled(DoubleStepHelper.next_step_args(left,right)(i))
}
}
class DoubleStandardStep2(left:StandardStep2, right:StandardStep2) extends StandardStep2
class DoubleUniqueStep1[-IL,-IR](left:UniqueStep1[IL], right:UniqueStep1[IR]) extends UniqueStep1[(IL,IR)] {
def next_step(i:(IL,IR)) = {
((l,r) => new DoubleUniqueStep2(l,r)).tupled(DoubleStepHelper.next_step_args(left,right)(i))
}
}
class DoubleUniqueStep2(left:UniqueStep2, right:UniqueStep2) extends UniqueStep2
このコード (scala 2.9.2) をコンパイルしようとすると、次のメッセージで失敗します。
型の不一致; 見つかった: (this.StandardStep2、this.StandardStep2) 必須: (this.UniqueStep2、this.UniqueStep2) ((l,r) => new DoubleUniqueStep2(l,r)).tupled(DoubleStepHelper.next_step_args(left,right)(i)) ^
は値DoubleStepHelper.next_step_args
を返すと想定されているため、これが発生すると想定しています。(StandardStep2, StandardStep2)
DoubleUniqueStep2
この問題を解決する方法を考えてもらえますか? DoubleStepHelper
next_step_args が(UniqueStep2, UniqueStep2)
ifSL
を返し、SR
から継承する可能性があることをコンパイラに伝える方法はUniqueStep1
?
優れた機能として、 の結果の型を(SL.next_step, SR.next_step)next_step_args
のように定義できることがあります。これは、戻り値の型が および の特定の関数 ( next_step )の戻り値の型から構築されることを意味します。SL
SR
「ビュー」境界は何らかの方法で解決できますか?
asInstanceOfを使用してキャストを強制することもできますが、これは見苦しく見えます。
ありがとう