84 votes

Pourquoi ne puis-je pas faire de String une instance d'une classe de types?

Donnée:

data Foo =
  FooString String
  …

class Fooable a where --(is this a good way to name this?)
  toFoo :: a -> Foo

Je veux faire de l' String d'une instance d' Fooable:

instance Fooable String where
  toFoo = FooString

GHC puis se plaint:

Illegal instance declaration for `Fooable String'
    (All instance types must be of the form (T t1 ... tn)
     where T is not a synonym.
     Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Fooable String'

Si j'utilise à la place [Char]:

instance Fooable [Char] where
  toFoo = FooString

GHC se plaint:

Illegal instance declaration for `Fooable [Char]'
   (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 `Fooable [Char]'

Question:

  • Pourquoi ne puis-je pas faire la Chaîne et de l'instance d'un typeclass?
  • GHC semble disposé à me laisser sortir avec cette si j'ajoute un indicateur supplémentaire. Est-ce une bonne idée?

65voto

hammar Points 89293

C'est parce qu' String est juste un alias de type pour [Char], ce qui est tout simplement la demande du constructeur de type [] sur le type Char, ce serait donc de la forme ([] Char). ce qui n'est pas de la forme (T a1 .. an) car Char n'est pas une variable de type.

La raison de cette restriction est d'éviter le chevauchement des instances. Par exemple, disons que vous avez un instance Fooable [Char], et puis quelqu'un plus tard est venu le long et défini un instance Fooable [a]. Maintenant que le compilateur ne sera pas en mesure de comprendre que l'on vous vouliez l'utiliser, et vous donnera une erreur.

En utilisant -XFlexibleInstances, vous êtes essentiellement en promettant de le compilateur de ne pas définir de tels cas.

En fonction de ce que vous essayez d'accomplir, il peut être préférable de définir un wrapper:

newtype Wrapper = Wrapper String
instance Fooable Wrapper where
    ...

18voto

Don Stewart Points 94361

Vous êtes en cours d'exécution dans deux limites de classique Haskell98 typeclasses:

  • ils interdire type de synonymes dans les instances
  • ils interdire les types imbriqués qui ne sont pas à son tour contenir des variables de type.

Ces lourdes restrictions sont levées par les deux extensions de langage:

  • -XTypeSynonymInstances

ce qui vous permet d'utiliser le type synoyms (comme String pour [Char]), et:

  • -XFlexibleInstances

qui de lever les restrictions sur les types d'instance, étant de la forme T a b .. où les paramètres sont des variables de type. L' -XFlexibleInstances indicateur permet à la tête de l'instance déclaration de mentionner arbitraire les types imbriqués.

Notez que la levée de ces restrictions peuvent parfois conduire à un chevauchement des cas, à quel point, d'une langue supplémentaire extension pourrait être nécessaire pour résoudre l'ambiguïté, permettant de GHC pour choisir un exemple pour vous.


Références::

4voto

Lemming Points 101

Les instances flexibles ne sont pas une bonne réponse dans la plupart des cas. De meilleures alternatives enveloppent la chaîne dans un newtype ou introduisent une classe d'assistance comme ceci:

 class Element a where
   listToFoo :: [a] -> Foo

instance Element Char where
   listToFoo = FooString

instance Element a => Fooable [a] where
   toFoo = listToFoo
 

Voir aussi: http://www.haskell.org/haskellwiki/List_instance

2voto

kowey Points 661

En ajoutant à ces réponses, si vous n'êtes pas à l'aise avec la levée des restrictions, il peut s'avérer judicieux de placer votre chaîne dans un nouveau type, ce qui peut être une instance d'une classe. Le compromis serait la laideur potentielle, devoir encapsuler et décompresser dans votre code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X