Question

Je joue autour de Haskell pour essayer d'obtenir le coup de lui. Je suis en problème avec mes classes de types. Ce que je suis en train de faire est de faire généraliser un module * en définissant des classes et des méthodes et je suis en train d'utiliser ceux d'un programme. Mon problème est que lorsque je tente de faire une liste de mes types de données Boîte une instance de ma classe Conseil (qui représente la carte) Je reçois l'erreur suivante:

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 d'une solution à cela, mais jusqu'à présent, je n'ai 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 les XFlexibleInstances générés par le message d'erreur ci-dessus, cependant, lorsque je tente que je reçois un message d'erreur lorsque je tente d'utiliser un élément de la liste en tant que 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ù j'essaie de faire des instances de ces classes est là 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
  ...

Les conseils dans la bonne direction serait appréciée.

Était-ce utile?

La solution

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 [Box] -> (Int, Int) -> Maybe Box de type, 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 ne pouvez pas les utiliser en tant que telle parce que toutes les fonctions nécessitent t être une instance de Tile).

Si vous avez besoin de dire « Une liste des carreaux est un conseil de tuiles » sans faire aussi toutes les autres listes dans les conseils, vous devez activer plusieurs paramètres classes de types 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
  ...
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top