Question

En venant de C ++, je trouve la programmation générique indispensable. Je me demande comment les gens approche que dans Haskell?

Dites comment ne pas écrire la fonction de permutation générique dans Haskell?

Y at-il un concept équivalent de spécialisation partielle dans Haskell?

C ++, je peux partiellement spécialiser la fonction générique d'échange avec un spécial pour un conteneur carte / hash_map générique qui a un procédé d'échange spécial pour O (1) échange de conteneur. Comment faites-vous que Haskell ou ce qui est l'exemple canonique de programmation générique dans Haskell?

Était-ce utile?

La solution

Ceci est étroitement lié à votre autre question au sujet de Haskell et quicksort. Je pense que vous avez probablement besoin de lire au moins Introduction d'un livre sur Haskell. Il semble que si vous ne l'avez pas encore saisi le point clé à ce sujet qui est qu'il vous interdit de modifier les valeurs des variables existantes.

Swap (comme compris et utilisé en C ++) est, par sa nature même, tout sur la modification des valeurs existantes. Il est donc nous pouvons utiliser un nom pour faire référence à un conteneur, et remplacer ce conteneur avec un contenu complètement différent, et de se spécialiser cette opération pour être rapide (et sans exception) pour les conteneurs spécifiques, ce qui nous permet de mettre en œuvre une approche modifier et republier (crucial pour l'écriture de code ou de tenter d'écrire du code sans exception de verrouillage de sécurité).

Vous pouvez écrire un swap générique dans Haskell, mais il serait sans doute prendre une paire de valeurs et retourner une nouvelle paire contenant les mêmes valeurs avec leurs positions renversées, ou quelque chose comme ça. Pas vraiment la même chose, et ne pas avoir les mêmes utilisations. Il ne serait pas de sens pour essayer de se spécialiser pour une carte en creusant l'intérieur de cette carte et échanger ses variables membres individuels, parce que vous êtes tout simplement pas autorisé à faire des choses comme ça dans Haskell (vous pouvez faire la spécialisation, mais pas la modification des variables).

Supposons que nous voulions "mesure" une liste dans Haskell:

measure :: [a] -> Integer

C'est une déclaration de type. Cela signifie que la fonction measure prend une liste de quoi que ce soit (a est un paramètre de type générique, car il commence par une lettre minuscule) et retourne un entier. Donc, cela fonctionne pour une liste de tout type d'élément -. Il est ce qu'on appellerait un modèle de fonction en C ++, ou une fonction polymorphique dans Haskell (pas la même chose en tant que classe polymorphique en C ++)

Nous pouvons maintenant définir qu'en fournissant des spécialisations pour chaque cas intéressant:

measure [] = 0

i.e.. mesurer la liste vide et vous obtenez zéro.

Voici une définition très générale qui couvre tous les autres cas:

measure (h:r) = 1 + measure r

Le bit entre parenthèses sur le LHS est un motif. Cela signifie: prendre une liste, cassez la tête et l'appeler h, appelez la partie restante r. Ces noms sont alors des paramètres que nous pouvons utiliser. Cela correspondra à une liste avec au moins un élément là-dessus.

Si vous avez essayé métaprogrammation modèle en C ++ cela sera vieux chapeau à vous, car elle implique exactement le même style - récursivité pour faire des boucles, la spécialisation pour faire la récursion fin. Sauf que dans Haskell il fonctionne lors de l'exécution (spécialisation de la fonction pour des valeurs particulières ou des motifs de valeurs).

Autres conseils

Comme Earwicker sais, l'exemple n'est pas aussi significatif dans Haskell. Si vous voulez absolument avoir de toute façon, voici quelque chose de similaire (permutant les deux parties d'une paire), c & p à partir d'une session interactive:

GHCi, version 6.8.2: http://www.haskell.org/ghc/  :? for help
Loading package base ... linking ... done.
Prelude> let swap (a,b) = (b,a)
Prelude> swap("hello", "world")
("world","hello")
Prelude> swap(1,2)
(2,1)
Prelude> swap("hello",2)
(2,"hello")

Dans Haskell, les fonctions sont aussi générique (polymorphes) que possible - le compilateur déduire la « plupart type général ». Par exemple, l'échange exemple de TheMarko est polymorphique par défaut en l'absence d'une signature de type:

* principal> let swap (a, b) = (b, a)
* Principal>: échange t
:: échange (t, t1) -> (t1, t)

En ce qui concerne la spécialisation partielle, GHC a une extension non-98:
  : /// C : /ghc/ghc-6.10.1/doc/users_guide/pragmas.html#specialize-pragma

En outre, notez qu'il ya une disparité dans la terminologie. Qu'est-ce qu'on appelle générique en C ++, Java et C # est appelé à polymorphes Haskell. « Générique » en Haskell signifie généralement polytypic:    http://haskell.readscheme.org/generic.html
Mais, aboe-je utiliser le sens c ++ du générique.

Dans Haskell vous devez créer des classes de type. classes de type ne sont pas comme les classes dans les langues OO. Prenez la classe de type numérique Il dit que tout ce qui est une instance de la classe peut effectuer certaines opérations (+ - * /) donc entier est membre de numérique et fournit des implémentations des fonctions nécessaires à considérer numérique et peuvent être utilisées partout où numérique est prévu.

Dites que vous voulez être en mesure de foo Ints et cordes. Ensuite, vous déclariez Int et chaîne à les instances de la classe FOO de type. Maintenant, lorsque vous voyez le type (Foo a) vous pouvez maintenant utiliser Int ou String.

La raison pour laquelle vous ne pouvez pas ajouter ints et flotte directement est parce que add a le type (numérique a) -> a -> aa est une variable de type et tout comme des variables ordinaires, il ne peut être tenue une fois le plus tôt comme vous le lier à Int tous un dans la liste doit être Int.

Après avoir lu assez dans un livre Haskell pour vraiment comprendre la réponse de Earwicker Je vous suggère également lire sur les classes de type. Je ne suis pas sûr de ce que la « spécialisation partielle » signifie, mais on dirait qu'ils pourraient se rapprocher.

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