155

I've come across a piece of Haskell code that looks like this:

ps@(p:pt)

What does the @ symbol mean in this context? I can't seem to find any info on Google (it's unfortunately hard to search for symbols on Google), and I can't find the function in the Prelude documentation, so I imagine it must be some sort of syntactic sugar instead.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
mipadi
  • 398,885
  • 90
  • 523
  • 479
  • 16
    Don't try to search for that specific symbol. Search for Haskell syntax in general, and then find the symbol in that overall discussion. For example, the top Google result for "Haskell syntax": http://www.cs.utep.edu/cheon/cs3360/pages/haskell-syntax.html. Second occurrence of `@` on that page explains it. – Rob Kennedy Jul 20 '09 at 13:17
  • 1
    Good thing I mentioned exactly how I found that URL, @Iter. Anyone can repeat the process today and find the answer on whatever page they find. – Rob Kennedy Mar 21 '17 at 00:00

4 Answers4

208

Yes, it's just syntactic sugar, with @ read aloud as "as". ps@(p:pt) gives you names for

  1. the list: ps
  2. the list's head : p
  3. the list's tail: pt

Without the @, you'd have to choose between (1) or (2):(3).

This syntax actually works for any constructor; if you have data Tree a = Tree a [Tree a], then t@(Tree _ kids) gives you access to both the tree and its children.

Nathan Shively-Sanders
  • 18,329
  • 4
  • 46
  • 56
55

The @ Symbol is used to both give a name to a parameter and match that parameter against a pattern that follows the @. It's not specific to lists and can also be used with other data structures.

This is useful if you want to "decompose" a parameter into it's parts while still needing the parameter as a whole somewhere in your function. One example where this is the case is the tails function from the standard library:

tails                   :: [a] -> [[a]]
tails []                =  [[]]
tails xxs@(_:xs)        =  xxs : tails xs
Nick
  • 8,480
  • 3
  • 37
  • 33
sth
  • 222,467
  • 53
  • 283
  • 367
29

I want to add that @ works at all levels, meaning you can do this:

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

Which will then produce this: ((Just 1, Just 2), Just 1, 1, 2)

So basically it's a way for you to bind a pattern to a value. This also means that it works with any kind of pattern, not just lists, as demonstrated above. This is a very useful thing to know, as it means you can use it in many more cases.

In this case, a is the entire Maybe Tuple, b is just the first Just in the tuple, and c and d are the values contained in the first and second Just in the tuple respectively

mkobit
  • 43,979
  • 12
  • 156
  • 150
Electric Coffee
  • 11,733
  • 9
  • 70
  • 131
12

To add to what the other people have said, they are called as-patterns (in ML the syntax uses the keyword "as"), and are described in the section of the Haskell Report on patterns.

newacct
  • 119,665
  • 29
  • 163
  • 224