2010-08-06 4 views
2

Je joue dans Haskell pour essayer de comprendre. Je rencontre des problèmes avec mes typeclasses. Ce que j'essaie de faire est de faire un module généralisé en définissant des classes et des méthodes, puis j'essaie d'utiliser celles-ci dans un programme. Mon problème est que lorsque je tente de faire une liste de mes types de données de la boîte une instance de ma classe de conseil (qui représente la carte) Je reçois l'erreur suivante:Liste des types personnalisés et des instances de la classe

Illegal instance declaration for `Board [Box]' 
    (All instance types must be of the form (T a1 ... an) 
    where a1 ... an are type *variables*, 
    and each type variable appears at most once in the instance head. 
    Use -XFlexibleInstances if you want to disable this.) 
In the instance declaration for `Board [Box]' 

J'ai été googler autour de une solution à cela, mais jusqu'à présent, j'ai seulement trouvé une page qui décrit une solution que je ne peux pas comprendre ici: http://www.haskell.org/haskellwiki/List_instance. Il décrit comment utiliser le XFlexibleInstances généré à partir du message d'erreur ci-dessus, cependant, lorsque j'essaie d'obtenir un message d'erreur lorsque j'essaie d'utiliser un élément de la liste comme un type de données Box.

Couldn't match expected type `t' against inferred type `Box' 
    `t' is a rigid type variable bound by 
     the type signature for `!!' at <no location info> 

Je ne sais pas si cela est une erreur bizarre que je fais ou si ma conception était tout simplement pas bon. Le code correspondant est ici:

class Tile a where 
    tilePosition :: a -> (Int, Int) 
    tileStatus :: a -> Status 

La classe du conseil d'administration doit être une liste de tuiles (ou une collection d'entre eux)

class Board b where 
    surroundingTiles :: Tile t => b -> (Int, Int) -> [t] 
    startingPosition :: b -> Maybe (Int, Int) 
    targetPosition :: b -> Maybe (Int, Int) 
    (!!)    :: Tile t => b -> (Int, Int) -> Maybe t 

Cela semble compiler, mais dans un autre fichier où je tente de faire instances de ces classes est où je reçois les erreurs

instance Board [Box] where 
    boxes !! pos = foldl (\acc b -> if boardPos b == pos then Just b else acc) Nothing boxes 
    ... 

Des conseils dans le bon sens seraient appréciés.

Répondre

1

Pour [Box] la fonction !! doit avoir le type Tile t => [Box] -> (Int, Int) -> Maybe t, ce qui signifie pour chaque type t qui est une instance de Tile vous devez être en mesure d'obtenir un t d'un [Box].

Cependant votre implémentation a le type [Box] -> (Int, Int) -> Maybe Box, ce qui signifie que vous ne pouvez obtenir un Box d'un [Box], ce qui ne fonctionne pas.

Qu'est-ce que vous pourriez faire pour obtenir ce que vous voulez est quelque chose comme ceci:

class Board b where 
    surroundingTiles :: Tile t => b t -> (Int, Int) -> [t] 
    startingPosition :: Tile t => b t -> Maybe (Int, Int) 
    targetPosition :: Tile t => b t -> Maybe (Int, Int) 
    (!!)    :: Tile t => b t -> (Int, Int) -> Maybe t 

instance Board [] where 
    ... 

De cette façon, vous pouvez utiliser des listes de toute instance de carreaux comme Boards (listes de toute autre chose sont aussi les conseils, mais vous pouvez ne les utilisez pas comme telles car toutes les fonctions nécessitent t pour être une instance de Tile).

Si vous avez besoin de dire « Une liste des carreaux est un conseil de tuiles » sans également faire toutes les autres listes dans les conseils, vous devez activer classes de types multi-paramètres qui vous permettent de dire des choses comme:

class Tile t => Board b t where 
    surroundingTiles :: b t -> (Int, Int) -> [t] 
    startingPosition :: b t -> Maybe (Int, Int) 
    targetPosition :: b t -> Maybe (Int, Int) 
    (!!)    :: b t -> (Int, Int) -> Maybe t 

instance Board [Tile] Tile where 
    ... 
+0

Wow, merci beaucoup pour une réponse détaillée. Le premier exemple que vous avez donné était suffisant pour me permettre de continuer. – Kuxi

Questions connexes