我在Haskell中编写了一个alpha-beta搜索,它使用NextMoveTag
类型系列来确保游戏状态和从该游戏状态生成的移动对于轮到它的玩家有效:
{-# LANGUAGE GADTs, EmptyDataDecls, DataKinds, TypeFamilies #-}
data MoveTag = ComputerMoveTag | PlayerMoveTag
type family NextMoveTag a where
NextMoveTag PlayerMoveTag = ComputerMoveTag
NextMoveTag ComputerMoveTag = PlayerMoveTag
data Move (t :: MoveTag) where
ComputerMove :: CardFace -> Row -> Col -> Move ComputerMoveTag
PlayerMove :: Direction -> Move PlayerMoveTag
data Game (t :: MoveTag) where
PlayerTurnGame :: Board -> Deck -> Game PlayerMoveTag
ComputerTurnGame :: Board -> Deck -> Move PlayerMoveTag -> Game ComputerMoveTag
staticEvaluator :: (Num f) => Game t -> f
nextGameStates :: Game t -> [(Move t, Game (NextMoveTag t))]
现在我想概括一下代码,以便我可以插入任何游戏,即
class Minimaxable g where
staticEvaluator :: ???
nextGameStates :: ???
但是我该怎么写这些类型?我可以吗?
我尝试写这个问题时遇到的一个问题是,alphabeta
的第一步是通过g
上的模式匹配检查轮到谁:
alphabeta depth alpha beta game@(PlayerTurnGame _ _) = ...
答案 0 :(得分:1)
这取决于您能够插入"任何游戏"的含义。每场比赛都会有一个MoveTag
表示轮到它了吗?如果是这样,那么您可以为g
提供一种类型的签名,并将类型类定义为
class Minimaxable (g :: MoveTag -> *) where
type GameMove g :: MoveTag -> *
staticEvaluator :: Num f => g t -> f
nextGameStates :: g t -> [(GameMove g t, g (NextMoveTag t))]
Move
类型作为关联类型同义词插入,因为它可能会因不同类型的游戏而异。
现在,您可以将现有游戏类型的实例定义为
instance Minimaxable Game where
type GameMove Game = Move
staticEvaluator = ...
nextGameStates = ...