Quel est l'effet du type synonymes sur les instances de classes de type? Qu'est-ce que le TypeSynonymInstances pragma à GHC faire?

StackOverflow https://stackoverflow.com/questions/2125674

  •  22-09-2019
  •  | 
  •  

Question

Je lis Real World Haskell Pg 151, et je l'ai regardé fixement au passage suivant pour plus d'une heure:

  

Rappelons que chaîne est synonyme de   [Char], qui à son tour est du type [a]   où Char est remplacé par le type   un paramètre. Selon Haskell 98 de   règles, nous ne sommes pas autorisés à fournir une   le type à la place d'un paramètre de type lorsque   nous écrivons une instance. En d'autres termes,   il serait légal pour nous d'écrire un   par exemple pour [a], mais pas pour [Char].   16 commentaires 5335

Il est tout simplement pas en train de sombrer dans. Fixant le la copie papier (gratuite non piraté) du chapitre 6 RWH Je vois d'autres personnes beaucoup sont vraiment souffrance avec cela. Je ne comprends toujours pas des commentaires ...

Tout d'abord, tout ce qui concerne ce qui me confond, alors s'il vous plaît si vous sentez que vous pouvez expliquer quoi que ce soit au sujet de ce passage, ou TypeSynonymInstances s'il vous plaît faire.

Voici mon problème:

  • Int est constructeur de données
  • String est constructeur de données de type synonyme

Maintenant, je ne peux pas répondre à ces questions:

  1. Pourquoi un synonyme de type empêche la réalisation du type d'un membre d'une classe de type (je suis à la recherche pour une raison quelconque qui se rapporte sans doute à la compilation ou d'un synonyme implimentation de type)?
  2. Pourquoi les concepteurs de la langue, veulent pas cette syntaxe (je demande raisonnement pas une théorie extensive ou des symboles mathématiques unicode).
  3. Je vois cette ligne « du type [a] où Char est remplacé par le paramètre de type a » , et je veux savoir pourquoi je ne peux pas le remplacer pour cette "la taper une où Int est remplacé par le paramètre de type d'un ".

Merci!

Était-ce utile?

La solution

Je pense qu'une partie de la question est que deux, en grande partie sans rapport, les restrictions sont en jeu:

  • Aucun cas de synonymes de type signifie que les instances ne peuvent être déclarés choses avec data ou newtype, non type. Cela interdit String, mais pas [Char].
  • Aucun cas flexibles signifie que les instances ne peuvent mentionner un type qui ne sont pas une variable, et seulement ce type peut être utilisé comme un constructeur de type. Cela interdit Maybe Int et f Int, mais pas Maybe a.

Voici ce que dit à propos GHCi Int, Char et String:

data Char = GHC.Types.C# GHC.Prim.Char#
data Int = GHC.Types.I# GHC.Prim.Int#
type String = [Char]

Int et Char sont les deux types simples sans paramètres variables de type; il n'y a pas de constructeur de type impliqué, vous pouvez donc faire avec eux des cas à peu près librement.

String, cependant, échoue sur les deux cas . Il est synonyme de type, ce qui est interdit, et il est aussi un constructeur de type appliqué à un non variable , à savoir le constructeur de type liste appliquée à Char.

A titre de comparaison, notez que [a], Maybe a et Either a b sont tous valides dans les cas, mais [Int], Maybe [a] et Either String a sont interdits; nous espérons que vous pouvez voir maintenant pourquoi.

En ce qui concerne vos questions directes, je ne sais pas ce que les motivations initiales étaient pour la conception de la langue de cette façon, et je ne suis nullement qualifié pour faire des déclarations faisant autorité sur les « meilleures pratiques », mais pour mon propre codage personnel Je ne hésite pas vraiment utiliser ces pragmas:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}

Vous pouvez toujours aller voir forfaits rel="noreferrer"> . cas flexibles, il semble, obtiennent une bonne quantité d'utilisation, et des paquets « respectables » (il y a un succès couple dans la source de parsecs, par exemple).

Autres conseils

En fait, ni Int ni String sont des constructeurs de données. Autrement dit, vous ne pouvez pas les utiliser pour créer une valeur de

> (Int 42, String "bob")
<interactive>:1:1: Not in scope: data constructor `Int'
<interactive>:1:9: Not in scope: data constructor `String'

Noms de Int un nouveau type de données distinctes, algébrique. String est un « type synonyme », ou alias, pour le type déjà existant: [Char]. Le problème est que Haskell 98 dit que vous ne pouvez pas utiliser un synonyme de type dans une déclaration d'instance.

Je ne peux pas dire pourquoi les auteurs du rapport Haskell 98 choisissent de restreindre les synonymes de type dans ce cas. Il y a un certain nombre de restrictions sur eux. Par exemple, ils ne peuvent pas être appliquées partiellement (si elles prennent des arguments de type). Je pense que la moindre idée vient à la fin de §4.2.2:

  

Les synonymes de type sont une pratique, mais   strictement syntaxique, le mécanisme pour faire   Type signatures plus lisible. UNE   synonymes et sa définition sont   complètement interchangeables, sauf dans   le type d'une instance de l'instance   Déclaration (Section 4.3.2).

On peut supposer que, il y avait une approche de compilation du programme, pour lequel cette interchangeabilité syntaxique aurait causé des problèmes pour les instances. Peut-être qu'il a à voir avec aspect notable des cas qu'ils fuite de paquets ...

Quant à votre dernière question, je crois que l'explication est l'amalgame entre deux choses: 1) String est synonyme de type pour [Char], qui est à son tour une spécialisation du type plus général [a] et 2) que, même sans le synonyme, [Char] ne peut pas être utilisé dans la tête d'une instance.

Ce second problème n'a rien à voir avec des synonymes de type, mais que les chefs d'instance doit avoir tous les paramètres de type au constructeur de type des variables, pas les types de béton. Autrement dit, vous ne pouvez pas définir des instances distinctes pour [Int] et [Char] pour une classe, vous ne pouvez défini une [a] instances. (Rappelez-vous que, malgré la syntaxe pratique, [] est un constructeur de type, et la chose est à l'intérieur du paramètre de type.)

Encore une fois, je ne sais pas pourquoi le rapport limite ceux-ci, mais je soupçonne que cela a aussi à voir avec la stratégie de compilation. Depuis la stratégie de compilation de GHC pour les instances peut gérer cela, vous pourrez vous détendre dans cette contrainte GHC via -XFlexibleInstances.

Enfin, j'ai vu les deux extensions activées dans beaucoup de code, mais peut-être quelqu'un avec plus d'expérience Haskell peut peser à si elles sont « bonnes pratiques » ou pas.

Int et chaîne sont des types, non données construtors. Chaîne se trouve être un alias pour qui peut également être écrite Liste Char [Char]. Un constructeur de données est quelque chose comme juste, si seulement 3 est une valeur de type Int Peut-être. Type cas de synonymes sont expliqués ici:

http://hackage.haskell.org/trac/haskell-prime / wiki / TypeSynonymInstances

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top