2010-06-13 103 views
4

我试图创建抽象的回合制游戏和人工智能(AI):奇怪斯卡拉错误

abstract class AGame { 
    type Player 
    type Move  // Player inside 

    def actPlayer : Player 
    def moves (player : Player) : Iterator[Move] 
    def play (move : Move) 
    def undo() 
    def isFinished : Boolean 
    def result (player : Player) : Double 
} 

abstract class Ai[Game <: AGame] { 
    def genMove (player : Game#Player) : Game#Move 
} 

class DummyGame extends AGame { 
    type Player = Unit 
    type Move = Unit 

    def moves (player : Player) = new Iterator[Move] { 
    def hasNext = false 
    def next = throw new Exception ("asd") 
    } 

    def actPlayer =() 

    def play (move : Move) { 
    } 

    def undo() { 
    } 

    def isFinished = true 

    def result (player : Player) = 0 
} 

class DummyAi[Game <: AGame] (game : Game) extends Ai[Game] { 
    override def genMove (player : Game#Player) : Game#Move = { 
    game.moves (player).next 
    } 
} 

我认为我必须使用这种奇怪的类型存取像游戏#球员。 我得到非常令人费解的错误。我想了解:

[error] /home/lew/Devel/CGSearch/src/main/scala/Main.scala:41: type mismatch; 
[error] found : Game#Player 
[error] required: DummyAi.this.game.Player 
[error]  game.moves (player).next 
[error]    ^
+0

这应该是'game.moves(player).next'还是'game.moves(player.next)'? Scala语法对于两种解释都是不明确的,但解析器需要选择一种语法。 – Theo 2010-06-13 17:41:35

+0

从错误消息中可以清楚地看到它被解析为第一个。 – 2010-06-13 18:59:32

回答

5

def moves (player : Player)意味着moves接受Game的球员。

Game#Player是玩家的类型任何Game。所以moves (player)是一种类型不匹配。

下面是一个简单的例子,它显示了为什么它必须是不匹配。假如它不是,看看接下来会发生什么:

class Game2 extends DummyGame { 
    override type Player = Boolean 
    override type Move = Boolean 

    override def moves(player : Boolean) = new Iterator[Boolean] {...} 
} 

val game2: DummyGame = new Game2 
// game2.Player is Boolean 

val dummyGameAi = new DummyAi[DummyGame](game2) 
// DummyGame#Player == Unit, so the type of genMove for Ai[DummyGame] is 
// def genMove (player : Unit) : Unit 

dummyGameAi.genMove(()) 
// this calls game2.moves(()), which doesn't typecheck 

为了得到这个工作,我们可以改变的genMove类型。如果我们通过游戏作为参数(这是有道理的呢),我们可以用路径依赖类型:

abstract class Ai[Game <: AGame] { 
    def genMove (game : Game)(player : game.Player) : game.Move 
    // now game.moves (player) typechecks 
} 
+0

我明白,但我仍然不知道该如何解决这个问题。任何想法 – 2010-06-13 22:27:28

+0

不会导致非法依赖方法类型错误? – BenjaminJackman 2010-06-14 19:16:46

+0

你使用了'-Xexperimental'选项吗? http://lampsvn.epfl.ch/trac/scala/ticket/128 – 2010-06-14 19:51:16

3

您可以通过在Ai引入抽象成员game解决你的问题,然后指定的路径依赖使用此成员类型:

abstract class Ai[Game <: AGame] { 
    val game : Game 
    def genMove (player : game.Player) : game.Move 
} 

class DummyAi[Game <: AGame] (val game : Game) extends Ai[Game] { 
    override def genMove (player : game.Player) : game.Move = { 
    game.moves (player).next 
    } 
}