Que signifie le symbole «@» en référence aux listes dans Haskell?

128

Je suis tombé sur un morceau de code Haskell qui ressemble à ceci:

ps@(p:pt)

Que signifie le @symbole dans ce contexte? Je n'arrive pas à trouver d'informations sur Google (il est malheureusement difficile de rechercher des symboles sur Google), et je ne trouve pas la fonction dans la documentation Prelude, donc j'imagine qu'il doit s'agir d'une sorte de sucre syntaxique à la place.

mipadi
la source
14
N'essayez pas de rechercher ce symbole spécifique. Recherchez la syntaxe Haskell en général, puis trouvez le symbole dans cette discussion générale. Par exemple, le meilleur résultat Google pour la "syntaxe Haskell": cs.utep.edu/cheon/cs3360/pages/haskell-syntax.html . La deuxième occurrence de @sur cette page l'explique.
Rob Kennedy
1
Heureusement, j'ai mentionné exactement comment j'ai trouvé cette URL, @Iter. N'importe qui peut répéter le processus aujourd'hui et trouver la réponse sur la page qu'il trouve.
Rob Kennedy

Réponses:

179

Oui, c'est juste du sucre syntaxique, avec @lu à haute voix comme "comme". ps@(p:pt)vous donne des noms pour

  1. la liste: ps
  2. la tête de la liste: p
  3. la queue de la liste: pt

Sans le @, vous devrez choisir entre (1) ou (2) :( 3).

Cette syntaxe fonctionne en fait pour n'importe quel constructeur; si c'est le cas data Tree a = Tree a [Tree a], alors t@(Tree _ kids)vous donne accès à l'arbre et à ses enfants.

Nathan Shively-Sanders
la source
3
connaissez-vous le nom de cette syntaxe?
danza
7
Cela s'appelle un "as-pattern"
adamo
41

Le @symbole est utilisé à la fois pour donner un nom à un paramètre et faire correspondre ce paramètre à un modèle qui suit le @. Il n'est pas spécifique aux listes et peut également être utilisé avec d'autres structures de données.

Ceci est utile si vous voulez "décomposer" un paramètre en ses parties tout en ayant besoin du paramètre dans son ensemble quelque part dans votre fonction. Un exemple où c'est le cas est la tailsfonction de la bibliothèque standard:

tails                   :: [a] -> [[a]]
tails []                =  [[]]
tails xxs@(_:xs)        =  xxs : tails xs
qc
la source
21

Je veux ajouter que cela @fonctionne à tous les niveaux, ce qui signifie que vous pouvez le faire:

let a @ (b @ (Just c), Just d) = (Just 1, Just 2) in (a, b, c, d)

Ce qui produira alors ceci: ((Just 1, Just 2), Just 1, 1, 2)

Donc, fondamentalement, c'est un moyen pour vous de lier un modèle à une valeur. Cela signifie également qu'il fonctionne avec n'importe quel type de modèle, pas seulement des listes, comme démontré ci-dessus. C'est une chose très utile à savoir, car cela signifie que vous pouvez l'utiliser dans de nombreux autres cas.

Dans ce cas, aest le tout Maybe Tuple, best juste le premier Justdans le tuple et cet dsont les valeurs contenues dans le premier et le second Justdans le tuple respectivement

Café électrique
la source
9

Pour ajouter à ce que les autres ont dit, ils sont appelés as-patterns (en ML la syntaxe utilise le mot-clé "as"), et sont décrits dans la section du rapport Haskell sur les patterns .

newacct
la source