我可以推广使用类型标签的GADT吗?

时间:2015-06-11 05:20:50

标签: haskell type-families

我在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 _ _) = ...

1 个答案:

答案 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  = ...