
I'm playing around with some types to represent a game board (like Go, Chess, Scrabble, etc). I'm using a type class to represent the basic Board interface, so I can change the implementation freely: class Board b pos piece where -- Update board with piece played at pos play :: b pos piece -> pos -> piece -> b pos piece -- Query pos to get piece (Nothing if off board) at :: b pos piece -> pos -> Maybe piece -- Empty board empty :: b pos piece and a Position on the board is represented thus: class Position p where up :: p -> p down :: p -> p left :: p -> p right :: p -> p With a concrete implementation using a tuple: instance (Enum c,Enum r) => Position (c,r) where up = second pred down = second succ left = first pred right = first succ My initial Board is a function: position -> Maybe piece, but I'm having a hard time writing the instance for it. My first attempt is: instance Board (pos -> Maybe piece) pos piece where empty = \_ -> Nothing at = ($) play b pos piece = move where move pos' | pos' == pos = Just piece | otherwise = b pos' but ghci complains: board.hs:34:15: Kind mis-match Expected kind `* -> * -> *', but `pos -> Maybe piece' has kind `*' In the instance declaration for `Board (pos -> Maybe piece) pos piece' Playing around with parentheses on the instance line got various similar messages, but I couldn't get anything to work. What am I missing here? One thing that strikes me is that "Board (pos -> Maybe piece) pos piece" has a lot of redundancy, and I'm wondering if I'm defining the Board type class wrong in the first place. Given that the "b" type parameter necessarily defines the position and pieces, I tried using dependent types: class Board b | b -> pos, b -> piece where ... but this complains "Not in scope: type variable `pos'/`piece'", so I tried sprinkling some existential types around as well: class (forall pos piece. b pos piece) => Board b | b -> pos, b -> piece where ... (with and without the dependent types) but this just complains "malformed class assertion". As you can probably tell, I'm just thrashing around trying things without really understanding what's going on here, so I'm hoping someone can give me some useful pointers. J