0

I am beginner in Haskell. I was doing simple excersice in Haskell which is to write compress function, since my code of this function was pretty long and not really what i wanted to do i checked the solution, and i found this one:

compress (x:ys@(y:_))
        | x == y = compress ys
        | otherwise = x : compress ys
compress ys = ys

The problem for me is the '@' which i don't really know what is doing, is there anyone out there willing to explain me how this works?

Goovie
  • 159
  • 1
  • 11
  • The other answers are correct. To cover another possibility, `@` also appears with the `TypeApplications` extension: https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/type_applications.html i.e. `@Int` – Peter Becich Mar 18 '23 at 21:23

3 Answers3

2

@ is used to bind a name to the value of the whole pattern match. Think of it like this

foo fullList@(x:xs) = ...

Is like saying

 foo (x:xs) = ...
   where fullList = x:xs

or, if you like

foo fullList = case fullList of 
    (x:xs) -> ...

So in your case

ys is equal to the tail of the original list, and the head of ys is y.

It's worth reading a good haskell tutorial to pick up some of this syntax.

Ingo
  • 36,037
  • 5
  • 53
  • 100
daniel gratzer
  • 52,833
  • 11
  • 94
  • 134
  • So how exactly can i understand: compress (x:ys@(y:_)) = --function code – Goovie Nov 14 '13 at 17:00
  • @GooviePopping Did you read the second to last line? `x` is the head of the list. `ys` is the tail. And `y` is the second element of the list. – daniel gratzer Nov 14 '13 at 17:03
  • @Ingo I don't mind the edit, but was there a semantic difference that I missed? – daniel gratzer Nov 14 '13 at 17:04
  • Yeah, of course i've read, but i just wanted to make sure i understand this. It's quite simple, but i just have get used to reading such concise code which looks quite common in Haskell. – Goovie Nov 14 '13 at 17:16
  • @jozefg Your version looks like there is a new value fullList made from (x:xs). (Not that it would make any difference in the presence of immutability.) I also believe that mine is the translation given in the Haskell 2010 report. – Ingo Nov 14 '13 at 17:25
  • compress (x:y:xs) | x == y = compress (y:xs) | otherwise = x : compress (y:xs) compress xs = xs Here is version without using '@' sign, what is actual difference between these two? Is the version in my first question more readable or at least faster? (i tried to add some new lines here, but it doesn't work, i hope it's not that hard to read for you). – Goovie Nov 14 '13 at 17:34
  • @Goovie The version without `@` creates a new `y:xs` list instead of reusing the already existing one. This *might* be less efficient. (I am not sure if it actually is in practice, GHC might notice it's identical and reuse it anyway.) – Ørjan Johansen Nov 15 '13 at 11:23
1

@ is used to pattern match a value while still keeping a reference to the whole value. An example is

data Blah = Blah Int Int

f :: Blah -> String
f val@(Blah x y) = -- some expression

f (Blah 1 2)

In the last call, val would be Blah 1 2, x would be 1 and y would be 2.

tomferon
  • 4,993
  • 1
  • 23
  • 44
0

I recommend you read the relevant section of Learn you a Haskell for a Great Good!

From the link:

There's also a thing called as patterns. Those are a handy way of breaking something up according to a pattern and binding it to names whilst still keeping a reference to the whole thing. You do that by putting a name and an @ in front of a pattern. For instance, the pattern xs@(x:y:ys). This pattern will match exactly the same thing as x:y:ys but you can easily get the whole list via xs instead of repeating yourself by typing out x:y:ys in the function body again.

DJG
  • 6,413
  • 4
  • 30
  • 51