[Haskell-cafe] Trying to sort out multiparameter type classes and their instances

Jeremy Fitzhardinge jeremy at goop.org
Tue Dec 1 17:34:46 EST 2009


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


More information about the Haskell-Cafe mailing list