27

Possible Duplicate:
Currying subtraction

I started my first haskell project that is not from a tutorial, and of course I stumble on the simplest things.

I have the following code:

moveUp y = modifyMVar_ y $ return . (+1)
moveDn y = modifyMVar_ y $ return . (-1)

It took me some time to understand why my code wouldn't compile: I had used (-1) which is seen as negative one. Bracketting the minus doesn't help as it prefixes it and makes 1 its first parameter.

In short, what is the point free version of this?

dec :: Num a => a -> a
dec x = x - 1
Community
  • 1
  • 1
Niriel
  • 2,605
  • 3
  • 29
  • 36

3 Answers3

31

I believe you want the conveniently-named subtract function, which exists for exactly the reason you've discovered:

subtract :: Num a => a -> a -> a

the same as flip (-).

Because - is treated specially in the Haskell grammar, (- e) is not a section, but an application of prefix negation. However, (subtract exp) is equivalent to the disallowed section.

If you wanted to write it pointfree without using a function like subtract, you could use flip (-), as the Prelude documentation mentions. But that's... kinda ugly.

C. A. McCann
  • 76,893
  • 19
  • 209
  • 302
7

If the above-mentioned subtract is too verbose, you could try something like (+ (-1)) or (-1 +).

Fixnum
  • 1,842
  • 1
  • 13
  • 25
  • 2
    This has the advantage of making my two lines of code symmetric, as (+1) and (subtract 1) don't look good side by side. However, this does not actually call (-). Of course that's totally fine with Num, but if I were working with sets that wouldn't work: adding the element -1 to a set isn't like removing the element 1. Subtract is more general, but I'll use your proposal. However, I'll have to accept the use of subtract or flip for this question, as it is a more direct answer. – Niriel Oct 11 '12 at 02:38
  • I'm not sure I understand your complaint, since (-) is only defined on instances of Num. (If you had non-commutative numbers this would be an issue.) – Fixnum Oct 11 '12 at 02:55
  • 6
    Since your numbers seem to be instances of `Enum` you could also use `succ` and `pred` instead. – Fixnum Oct 11 '12 at 02:56
4

You can use the subtract function (which is in the Standard Prelude).

moveDn y = modifyMVar_ y $ return . (subtract 1)

You can also use flip to reorder the parameters that - takes.

moveDn y = modifyMVar_ y $ return . (flip (-) 1)
bisserlis
  • 633
  • 4
  • 10