Что означает символ «@» в отношении списков в Haskell?

128

Я наткнулся на фрагмент кода Haskell, который выглядит так:

ps@(p:pt)

Что означает @символ в этом контексте? Кажется, я не могу найти никакой информации в Google (к сожалению, сложно искать символы в Google), и я не могу найти функцию в документации Prelude, поэтому я полагаю, что вместо этого это должен быть какой-то синтаксический сахар.

mipadi
источник
14
Не пытайтесь искать именно этот символ. Найдите синтаксис Haskell в целом, а затем найдите символ в этом общем обсуждении. Например, лучший результат Google по запросу "Синтаксис Haskell": cs.utep.edu/cheon/cs3360/pages/haskell-syntax.html . Второе появление @на этой странице объясняет это.
Роб Кеннеди,
1
Хорошо, что я точно упомянул, как я нашел этот URL, @Iter. Кто угодно может повторить этот процесс сегодня и найти ответ на любой странице, которую он найдет.
Роб Кеннеди,

Ответы:

179

Да, это просто синтаксический сахар, @читаемый вслух как «как». ps@(p:pt)дает вам имена для

  1. список: ps
  2. начало списка: p
  3. хвост списка: pt

Без символа @вам придется выбирать между (1) или (2) :( 3).

Этот синтаксис действительно работает для любого конструктора; если да data Tree a = Tree a [Tree a], то t@(Tree _ kids)дает вам доступ как к дереву, так и к его дочерним элементам.

Натан Шивели-Сандерс
источник
3
вы знаете название этого синтаксиса?
danza
7
Это называется «как образец»
Адамо
41

@Символ используется для обоих дать имя параметра и соответствовать этому параметру от шаблона , который следует за @. Это не относится к спискам, а также может использоваться с другими структурами данных.

Это полезно, если вы хотите «разложить» параметр на части, но при этом вам нужен параметр в целом где-то в вашей функции. Один из примеров, когда это так, - это tailsфункция из стандартной библиотеки:

tails                   :: [a] -> [[a]]
tails []                =  [[]]
tails xxs@(_:xs)        =  xxs : tails xs
STH
источник
21

Я хочу добавить, что это @работает на всех уровнях, то есть вы можете сделать это:

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

Что затем произведет это: ((Just 1, Just 2), Just 1, 1, 2)

По сути, это способ привязать шаблон к значению. Это также означает, что он работает с любым типом шаблона, а не только со списками, как показано выше. Это очень полезная вещь, поскольку это означает, что вы можете использовать ее во многих других случаях.

В этом случае a- это все Maybe Tuple, bэто только первое Justв кортеже, cи d- значения, содержащиеся в первом и втором Justв кортеже соответственно.

Электрический кофе
источник
9

Чтобы добавить к сказанному другими, они называются как-шаблонами (в синтаксисе ML используется ключевое слово "as") и описаны в разделе отчета Haskell о шаблонах .

newacct
источник