O que o símbolo “@” significa em referência às listas em Haskell?

127

Eu me deparei com um pedaço de código Haskell que se parece com isso:

ps@(p:pt)

O que o @símbolo significa neste contexto? Parece que não consigo encontrar nenhuma informação no Google (infelizmente é difícil procurar símbolos no Google) e não consigo encontrar a função na documentação do Prelude, então imagino que deva ser algum tipo de açúcar sintático.

mipadi
fonte
14
Não tente procurar esse símbolo específico. Procure a sintaxe Haskell em geral e encontre o símbolo nessa discussão geral. Por exemplo, o principal resultado do Google para "Sintaxe Haskell": cs.utep.edu/cheon/cs3360/pages/haskell-syntax.html . A segunda ocorrência @dessa página explica isso.
Rob Kennedy
1
Ainda bem que mencionei exatamente como encontrei esse URL, @Iter. Qualquer pessoa pode repetir o processo hoje e encontrar a resposta em qualquer página que encontrar.
Rob Kennedy

Respostas:

179

Sim, é apenas açúcar sintático, com @lido em voz alta como "como". ps@(p:pt)dá-lhe nomes para

  1. a lista: ps
  2. o cabeçalho da lista: p
  3. a cauda da lista: pt

Sem o @, você teria que escolher entre (1) ou (2) :( 3).

Essa sintaxe realmente funciona para qualquer construtor; se tiver data Tree a = Tree a [Tree a], então t@(Tree _ kids)você terá acesso à árvore e a seus filhos.

Nathan Shively-Sanders
fonte
3
você sabe o nome dessa sintaxe?
Danza
7
É chamado de "como padrão"
adamo
41

O @símbolo é usado para dar um nome a um parâmetro e corresponder esse parâmetro a um padrão que segue o @. Não é específico para listas e também pode ser usado com outras estruturas de dados.

Isso é útil se você quiser "decompor" um parâmetro em suas partes enquanto ainda precisar do parâmetro como um todo em algum lugar da sua função. Um exemplo em que esse é o caso é a tailsfunção da biblioteca padrão:

tails                   :: [a] -> [[a]]
tails []                =  [[]]
tails xxs@(_:xs)        =  xxs : tails xs
sth
fonte
21

Quero acrescentar que @funciona em todos os níveis, o que significa que você pode fazer isso:

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

O que produzirá isso: ((Just 1, Just 2), Just 1, 1, 2)

Então, basicamente, é uma maneira de vincular um padrão a um valor. Isso também significa que ele funciona com qualquer tipo de padrão, não apenas com listas, como demonstrado acima. É uma coisa muito útil para saber, pois significa que você pode usá-lo em muitos outros casos.

Nesse caso, aé o inteiro Maybe Tuple, bé apenas o primeiro Justna tupla ce dsão os valores contidos no primeiro e Justno segundo na tupla, respectivamente

Café elétrico
fonte
9

Para adicionar o que as outras pessoas disseram, elas são chamadas de padrões (no ML, a sintaxe usa a palavra-chave "como") e são descritas na seção do Relatório Haskell sobre padrões .

newacct
fonte