3

I am new to Haskell and I am trying to calculate the maximum segment sum,

(@) :: Int -> Int -> Int
x @ y = 0 `max` (x + y)

mss2 :: [Int] -> Int
mss2 = maximum . scanr (@) 0

The error is

No Modules Loaded for (@)

I found this snippet in Richard Bird's text. What am I missing here? Are there other ways to declare/overload the operators, is my approach wrong?

Brian61354270
  • 8,690
  • 4
  • 21
  • 43
Swap D
  • 93
  • 5
  • 2
    `x @ y = ...` doesn't mean what you think it does. `@` is being used as an [as-pattern](https://www.haskell.org/tutorial/patterns.html), not as a infix operator. Give `x @ [a,b] = [1,2]` a try, and then check `x`, `a`, and `b`. – Brian61354270 May 15 '21 at 01:36
  • 4
    Yes, `@` is in effect a reserved symbol. (It has special effect as 'type appllication' in advanced Haskell, for example.) I wouldn't try to use it as an ordinary operator. – AntC May 15 '21 at 01:57
  • I tried the above functions, instead of `@` I used `$` by hiding its the original implementation and it works just fine. So it means `@` is not an ordinary operator. Thank you for your help @Brian and @AntC – Swap D May 15 '21 at 02:05
  • 4
    You can also try `@@`, `.@`, `@.` or some other variation, but `@` is one of the reserved symbols, like `->` and `::`. – chi May 15 '21 at 08:23
  • 1
    Related to [SO question 30326249](https://stackoverflow.com/questions/30326249/what-does-mean-in-haskell). – jpmarinier May 15 '21 at 08:51

1 Answers1

1

It appears that in the context of that book, (@) is being used as a stand-in for some binary operator such as (+) or (<>), even though this is not actually legal Haskell syntax.

For questions about Haskell syntax, it’s helpful to consult the Haskell 2010 Report.

In Ch. 2 Lexical Structure, under §2.2 Lexical Program Structure, you can find @ in the grammar of symbols that may appear in an operator name:

symbolascSymbol | uniSymbolspecial | _ | " | '

ascSymbol! | # | $ | % | & | | + | . | / | < | = | > | ? | @ | \ | ^ | | | - | ~ | :

And §2.4 Lexical Structure: Identifiers and Operators defines valid operator names to include such symbols:

varsym → ( symbol: {symbol} )reservedop | dashes

consym → ( : {symbol} )reservedop

However, the subscript in angle brackets denotes a “difference” or exclusion, so this disallows a list of reserved identifiers. Under the production reservedop you can find that @ appears in that list:

reservedop.. | : | :: | = | \ | | | <- | -> | @ | ~ | =>

The reason is that the @ symbol denotes an “as” pattern, described in §3.17.2.8 Informal Semantics of Pattern Matching:

  1. Matching an as-pattern var@apat against a value v is the result of matching apat against v, augmented with the binding of var to v.

As patterns are very useful for controlling the sharing of values and making certain definitions more concise, e.g.:

-- | Merge two sorted lists.
merge :: (Ord a) => [a] -> [a] -> [a]

-- ‘as0’ & ‘bs0’ denote the original input lists.
-- ‘as’ & ‘bs’ denote their tails.

merge as0@(a : as) bs0@(b : bs) = case compare a b of

  -- ‘as0’ passes along the same list cell;
  -- repeating ‘a : as’ would allocate a /new/ cell.

  GT -> b : merge as0 bs
  _  -> a : merge as  bs0

merge [] bs0 = bs0
merge as0 [] = as0

Therefore, the definition:

x @ y = 0 `max` (x + y)

Or more conventionally written x@y = …, is equivalent to defining two variables referring to the same value, which furthermore is defined recursively:

x = 0 `max` (x + y)
y = x

Without the type signature Int -> Int -> Int, this definition would be accepted, defining x, y :: (Ord a, Num a) => a, but attempting to evaluate either variable would produce an infinite loop, since this is “unproductive” recursion.

The solution is to use a non-reserved symbol as your operator name instead, such as <@> or +..

I can’t find a citation for this, but it’s possible that GHC used to accept this syntax, even though it was also disallowed by the Haskell 98 Report which was current at the time the first edition of this book came out, and that this example code just wasn’t updated for the second edition.

Jon Purdy
  • 53,300
  • 8
  • 96
  • 166