Can I generalize the GADTs that use type tags?
I wrote an alpha-beta search in Haskell that uses the type family NextMoveTag
to ensure that the game state and movements created from that game state are valid for the player whose turn it is:
{-# 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))]
Now I would like to generalize the code so that I can connect any game, i.e.
class Minimaxable g where
staticEvaluator :: ???
nextGameStates :: ???
But how do you write types? Can I?
The problem I run into when I try to write this down is that the first step alphabeta
is to check whose twist is by pattern matching on g
:
alphabeta depth alpha beta game@(PlayerTurnGame _ _) = ...
source to share
It depends on what you mean by being able to connect "any game". Will each game have a MoveTag
designation of what is the queue? If so, then you can give g
a view signature and define the type class as
class Minimaxable (g :: MoveTag -> *) where
type GameMove g :: MoveTag -> *
staticEvaluator :: Num f => g t -> f
nextGameStates :: g t -> [(GameMove g t, g (NextMoveTag t))]
Type is Move
included as an associated synonym for type, as it is likely to be different between different types of games.
Now you can define an instance for your existing game type as
instance Minimaxable Game where
type GameMove Game = Move
staticEvaluator = ...
nextGameStates = ...
source to share