Haskell pattern matching - ce que c'est?
Qu'est-ce que la correspondance de motif en Haskell et comment est-il lié à gardé équations?
J'ai essayé de chercher une explication simple, mais je n'ai pas trouvé un.
EDIT:
Quelqu'un étiquetés comme des devoirs. Je n'ai pas plus aller à l'école, je suis en train d'apprendre Haskell et j'essaie de comprendre ce concept. Pur intérêt.
- Peut-être devrait également inclure le pattern matching concept en F#, ainsi...
- Tonnes de langues ont de la correspondance de modèle, pas seulement Haskell et F#.
- C'est une caractéristique commune de pur-fonctionnelle et de la contrainte langues. Prolog, Erlang et SML, par exemple.
- L'article de wikipédia semble être assez bonne. Le Pattern matching est fondamentale pour les langues telles que le Haskell, Scala et beaucoup d'autres encore. Je pense que l'obtention de votre tête ronde de la langue est essentielle à la compréhension de la correspondance de motif. Je voudrais obtenir de l'apprentissage de Haskell et ne pas vous soucier de trouver une définition sur le filtrage prématurément. La compréhension viendra!
- J'ai ajouté de la langue-agnostique. Évidemment, je ne veux pas supprimer Haskell, mais comme il est applicable à de nombreuses langues, j'ai ajouté un FP balise ainsi.
- J'ai marqué comme devoirs purement parce que la question sonne comme une reformulation de la question de la fin du chapitre d'un manuel, avec peu de preuves de recherche fournis.
- oui, il pourrait avoir été le cas, mais dans mon cas, il ne l'est pas. Pas de soucis bien 🙂
- c'est une option, mais ma ne pas comprendre cela, de le rendre plus difficile à obtenir pour la compréhension d'autres concepts qui pourraient être construits sur elle?
- ce que je veux dire, c'est que toute introduction à Haskell permettra de vous familiariser avec le modèle correspondant dans un "confort" de manière. Vous ne pouvez pas vraiment comprendre la correspondance de motif, sans comprendre les types de liaison, etc qui vous permettra d'apprendre le long de la route de toute façon. Une fois que vous avez écrit quelques fonctions qui opèrent sur des valeurs, les tuples et les listes que vous aurez 'get' il. Il est très différent de C#. FWIW, Scala pourraient être d'intérêt pour vous, en cours de Programmation Fonctionnelle hybride avec OO et Java (qui avouons-le est très similaire .NET!).
- Je ne recommanderais pas de Scala pour une introduction à la programmation fonctionnelle. Il est fonctionnel dans une main-ondulés, sorte de façon, mais c'est aussi OO, ce qui le rend plus difficile à apprendre les aspects fonctionnels bien. F# est plus fortement fonctionnel, de sorte que je recommande pour un programmeur C# (et il est .NETTE) avant de Scala.
- oui tout à fait, éventuellement, je n'ai pas regardé F#. J'ai juste trouvé que la Scala approche du motif de correspondance avec des classes de cas et des extracteurs et comment ils se rapportent à des catégories telles que les tuples et les listes de particulièrement fascinant à la fois d'une OO et FP point de vue. Haskell est un beau terrain neutre' à partir de laquelle commencer.
Vous devez vous connecter pour publier un commentaire.
En un mot, les modèles sont comme la définition de fonctions par morceaux en mathématiques. Vous pouvez spécifier différents corps de fonction pour les différents arguments à l'aide de modèles. Lorsque vous appelez une fonction, l'organe compétent est choisi en comparant les arguments avec les différents argument modèles. Lire Une Introduction en Douceur à Haskell pour plus d'informations.
Comparer:
avec l'équivalent Haskell:
Note le "n ≥ 2" dans le cas de la fonction devient un garde dans le Haskell version, mais les deux autres conditions sont tout simplement des modèles. Les modèles sont des conditions que les valeurs de test et de la structure, comme
x:xs
,(x, y, z)
, ouJust x
. Dans un par morceaux définition, les conditions d'=
ou∈
relations (fondamentalement, les conditions qui disent quelque chose "est" quelque chose d'autre) deviennent des motifs. Les gardes de permettre plus de conditions générales. Nous pourrions réécrirefib
à utiliser des gardes:Il y a d'autres bonnes réponses, je vais donc vous donner une réponse très technique. Le Pattern matching est le élimination construire pour types de données algébriques:
"L'élimination de construire" signifie "manière de consommer ou d'utiliser une valeur"
"Algébrique" type de données, en plus de la première classe de fonctions, est la grande idée dans un langage fonctionnel typé statiquement comme Propre, F#, Haskell, ou ML
L'idée de types de données algébriques, c'est que vous définissez un type de chose, et de vous dire toutes les façons dont vous pouvez faire cette chose. Comme exemple, nous allons définir la "Séquence de Chaîne" comme un type de données algébrique, avec trois façons de faire:
Maintenant, il ya toutes sortes de choses de mal avec cette définition, mais comme un exemple, il est intéressant car il fournit à constante de temps de concaténation de séquences de longueur arbitraire. (Il y a d'autres moyens d'y parvenir.) La déclaration introduit
Empty
,Cat
, etSingle
, qui sont de toutes les façons il y a de faire des séquences. (Qui fait de chacun un introduction construire—une façon de faire les choses.)Cat
, vous avez besoin de deux autres séquences.Single
, vous avez besoin d'un élément (dans ce cas, une chaîne de caractères)Voici le punch line: l'élimination de construire, pattern matching, vous donne un moyen d'examiner une séquence et lui poser la question ce constructeur ont été effectuées avec?. Parce que vous devez être préparé pour toute réponse, vous devez fournir au moins une solution de rechange pour chaque constructeur. Voici une longueur de fonction:
À la base de la langue, toute la correspondance de modèle est construit sur cette
case
construire. Toutefois, en raison des types de données algébriques et le pattern matching sont si importants pour les idiomes de la langue, il y spéciale du "sucre syntaxique" pour faire du pattern matching dans le formulaire de déclaration d'une définition de fonction:Avec ce sucre syntaxique, le calcul par la correspondance de modèle ressemble beaucoup à la définition donnée par les équations. (Le Haskell comité a fait exprès.) Et comme vous pouvez le voir dans les autres réponses, il est possible de se spécialiser soit une équation ou d'une variante dans un
case
expression en appliquant un garde sur elle. Je ne peux pas penser à une plausible de la garde pour la séquence de l'exemple, et il y a beaucoup d'exemples dans les autres réponses, donc je vais le laisser là.Pattern matching est, au moins en Haskell, profondément liée à la notion de types de données algébriques. Lorsque vous déclarez un type de données comme ceci:
...il définit
Foo
,Bar
, etBaz
comme constructeurs--à ne pas confondre avec les "constructeurs" en programmation orientée objet,--que la construction d'unSomeData
de la valeur pour les autres valeurs.Pattern matching est rien de plus que de faire cela dans le sens inverse--un modèle "déconstruire" un
SomeData
valeur dans ses éléments constitutifs (en fait, je crois que le pattern matching est le seulement façon à extraire des valeurs en Haskell).Lorsqu'il y a plusieurs constructeurs pour un type, vous pouvez écrire plusieurs versions d'une fonction pour chaque modèle, avec le bon d'être sélectionné selon le constructeur a été utilisé (en supposant que vous avez écrit modèles pour correspondre à toutes les constructions--ce qui est généralement une bonne pratique de le faire).
Dans un langage fonctionnel, le filtrage consiste à vérifier un argument contre les différentes formes. Un exemple simple consiste définie de manière récursive les opérations sur les listes. Je vais utiliser OCaml pour expliquer la correspondance de modèle puisque c'est ma fonctionnelle de la langue de leur choix, mais les concepts sont les mêmes en F#, et Haskell, autant que je sache.
Ici est la définition d'une fonction pour calculer la longueur d'une liste
lst
. En OCaml, une `une listeis defined recursively as the empty list
[], or the structure
h::t, where
his an element of type
un(
unbeing any type we want, such as an integer or even another list),
tis a list (hence the recursive definition), and
::` est l'opérateur cons, qui crée une nouvelle liste d'un élément et une liste.Donc la fonction devrait ressembler à ceci:
rec
est un modificateur qui raconte OCaml qu'une fonction peut s'appeler elle-même de manière récursive. Ne vous inquiétez pas à propos de cette partie. Lematch
instruction est ce que nous nous concentrons sur. OCaml va vérifierlst
contre les deux modèles - la liste est vide, ouh :: t
- et de renvoyer une valeur différente sur cette base. Puisque nous savons que chaque liste correspond à un seul de ces modèles, nous pouvons être assurés que notre fonction va retourner en toute sécurité.Noter que même si ces deux modèles sera de prendre soin de toutes les listes, vous n'êtes pas limité à eux. Un modèle de type
h1 :: h2 :: t
(correspondant à toutes les listes de longueur 2 ou plus) est également valide.Bien sûr, l'utilisation de motifs de ne pas restreindre de manière récursive défini des structures de données, ou des fonctions récursives. Voici un (fictive) de la fonction pour savoir si un nombre est 1 ou 2:
Dans ce cas, les formes de notre modèle sont les nombres eux-mêmes.
_
est un spécial " fourre-tout utilisé comme un cas de défaut, au cas où aucune de ces tendances correspondent.Pattern matching est l'un de ces opérations douloureuses qui est difficile à obtenir la tête autour de si vous venez de la programmation procédurale arrière-plan. Je trouve cela difficile à obtenir en raison de la même syntaxe utilisée pour créer une structure de données peut être utilisée pour la correspondance.
En F#, vous pouvez utiliser l'opérateur cons
::
pour ajouter un élément au début d'une liste comme ceci:De même, vous pouvez utiliser le même opérateur pour diviser la liste en haut comme ceci:
Just
(une commune de Haskell).