148
votes

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.

4
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": cs.utep.edu/cheon/cs3360/pages/haskell-syntax.html. Second occurrence of @ on that page explains it.Rob Kennedy
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

4 Answers

195
votes

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.

52
votes

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
25
votes

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

11
votes

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.