【发布时间】:2017-01-04 23:16:55
【问题描述】:
我正在实现一些功能来搜索游戏树以供自己娱乐。例如,一个这样的函数将执行Minimax 算法。这些函数使用两种对象:
- 游戏状态,例如棋盘上棋子的位置、下一个要移动的玩家等。
- 移动,例如“典当 e2 到 e5”
我的目标是拥有适用于不同游戏的搜索功能,因此我将游戏特定知识作为辅助函数传递,例如:
- 从给定的游戏状态生成所有可能的移动
- 给定状态和移动,将移动应用到状态以获得结果状态
- 找出这是否是一个获胜的位置
- 等
这样一来,我的搜索功能确实不是特定于游戏的,但解决方案仍然感觉不对。这也使我的参数列表相当长:
-- Given a game state find the best next move
bestMove :: s -> (s -> [m]) -> (s -> m -> s) -> m -- more parameters in my real code
bestMove currentState possibleMoves applyMove = ...
问题
我可以用类型类替换这些辅助函数吗?我正在寻找类似的东西:
class Move m where
apply :: State s => s -> m -> s
class State s where
possibleMoves :: Move m => s -> [m]
bestMove :: State s => Move m => s -> m
bestMove currentState = ... -- e.g. = head $ possibleMoves state
问题是State 的任何实例只能与Move 的一个特定实例一起工作,反之亦然:
{-# LANGUAGE InstanceSigs #-}
data ChessState = ...
data ChessMove = ...
instance Move ChessMove where
apply :: ChessState -> ChessMove -> ChessState
apply s m = ...
apply 的类型签名当然是错误的。应该是
apply :: S s => s -> ChessMove -> s
但我确实需要特定于ChessState 的属性才能创建ChessMove。
我的整个想法完全走错了轨道,还是有办法编码ChessState和ChessMove之间的关系?我在使用 MultiParamTypeClasses 方面取得了一些进展,但它仍然不像我希望的那样。
【问题讨论】: