As some form of experimentation, I am trying to define a very general logic for card games in Haskell. To guarantee the maximal level of abstraction, I define the following type class:
class (Monad m) => CardGame m where
data Deck m :: *
data Card m :: *
data Player m :: *
game :: m () -- a description of the game's rules
draw :: Deck m -> m (Card m) -- top card of deck is drawn
pick :: Deck m -> Player m -> m (Card m) -- player selects card from a deck
-- so on and so forth
This class is very satisfying to me because it leaves open what cards will be used (e.g. tarot card, French suited, German suited, etc.), who the players are, etc., and what kind of underlying monad the game should be run into.
Now suppose I want to define War-like card games. These games are played between two players, each player receiving one deck, on a French-suited card game but there are many variants of the game itself so I can't specify ahead of time what the exact rules will be (i.e. the instantiation of game) How can I partially specialize the type class above? The compiler gets upset at the following:
data Suit = Heart | Diamond | Spade | Club
data Value = Number Int | Jack | Queen | King
data FrenchSuited = Card Suit Value
class (Game m) => War m where
-- syntax error in the following line:
data Card m = FrenchSuited -- any War-like game must be played on French-suited card
deck1 :: Deck m
deck2 :: Deck m
player1 :: Player m
player2 :: Player m
Do you see a way I can accomplish this?
PS: War-like games can be played with any type of cards really but it's just an example. I am more interested in how one can achieve the type of partial specialization of type classes I am after.