私は 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を与える特別なタイプであり、明らかにそのために継承する必要があります。UniqueStep2next_stepUniqueStep2StandardStep2
ここで、DoubleStepラッパーを作成する必要がありました。sDoubleStandardStep1もラップし、呼び出されたときにStandardStep1a を返します。
同じことを行いますが、 を返します。DoubleStandardStep2next_stepDoubleUniqueStep1DoubleUniqueStep2
*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
この問題を解決する方法を考えてもらえますか? DoubleStepHelpernext_step_args が(UniqueStep2, UniqueStep2)ifSLを返し、SRから継承する可能性があることをコンパイラに伝える方法はUniqueStep1?
優れた機能として、 の結果の型を(SL.next_step, SR.next_step)next_step_argsのように定義できることがあります。これは、戻り値の型が および の特定の関数 ( next_step )の戻り値の型から構築されることを意味します。SLSR
「ビュー」境界は何らかの方法で解決できますか?
asInstanceOfを使用してキャストを強制することもできますが、これは見苦しく見えます。
ありがとう