我似乎不了解 Scala 类型系统。我正在尝试实现两个基本特征和一个特征,以供一系列算法使用。我在下面做错了什么?
动作和状态的基本特征;这些被简化为仅包括暴露问题的方法。
trait Move
trait State[M <: Move] {
def moves: List[M]
def successor(m: M): State[M]
}
这是使用上述算法的家族的特征。我不确定这是否正确!可能涉及一些+M / -S的东西......
trait Algorithm {
def bestMove[M <: Move, S <: State[M]](s: S): M
}
具体动作和状态:
case class MyMove(x: Int) extends Move
class MyState(val s: Map[MyMove,Int]) extends State[MyMove] {
def moves = MyMove(1) :: MyMove(2) :: Nil
def successor(p: MyMove) = new MyState(s.updated(p, 1))
}
关于以下内容,我的立场非常不稳定,但编译器似乎接受了它......试图对算法特征进行具体实现。
object MyAlgorithm extends Algorithm {
def bestMove(s: State[Move]) = s.moves.head
}
到目前为止没有编译错误;但是,当我尝试将所有部分放在一起时,它们会出现:
object Main extends App {
val s = new MyState(Map())
val m = MyAlgorithm.bestMove(s)
println(m)
}
上面抛出了这个错误:
error: overloaded method value bestMove with alternatives:
(s: State[Move])Move <and>
[M <: Move, S <: State[M]](s: S)M
cannot be applied to (MyState)
val m = MyAlgorithm.bestMove(s)
^
更新:按照建议,我将算法特征更改为使用抽象类型成员。这解决了我所说的问题,但我把它简化了一点。MyAlgorithm.bestMove()
必须允许该方法使用 s.successor(m) 的输出调用自身,如下所示:
trait Algorithm {
type M <: Move
type S <: State[M]
def bestMove(s: S): M
}
trait MyAlgorithm extends Algorithm {
def score(s: S): Int = s.moves.size
def bestMove(s: S): M = {
val groups = s.moves.groupBy(m => score(s.successor(m)))
val max = groups.keys.max
groups(max).head
}
}
以上给出了2个错误:
Foo.scala:38: error: type mismatch;
found : State[MyAlgorithm.this.M]
required: MyAlgorithm.this.S
val groups = s.moves.groupBy(m => score(s.successor(m)))
^
Foo.scala:39: error: diverging implicit expansion for type Ordering[B]
starting with method Tuple9 in object Ordering
val max = groups.keys.max
^
我是否必须转向使用特征特征的方法,也就是蛋糕模式,才能使这项工作有效?(我只是在这里猜测;我仍然非常困惑。)