6

For functions with three or more arguments, how does currying work?

I searched over SO and Google. Concrete examples given in e.g. What is 'Currying'? ; https://en.wikipedia.org/wiki/Currying are about binary functions f (x, y).

In that case, g = curry f takes one parameter and produces a unary function (f x).

My question is:

How do we extend this consistently to a n-parameter function, e.g. f3 (x,y,z)? (f3: X->Y->Z->U)

If the curry operation is treated as a higher order function, it can't directly apply to f3, because curry expects a function of type (X,Y) -> Z, and the argument of f3 is a triple, not a pair. The same issue arises with a function fn that takes an n-tuple.

One solution might be to equate (x,y,z) and (x,(y,z)), then curry seems to apply. Then curry f3 = (f3 x) is of type (Y,Z) -> U. But is this how curry is supposed to be?

Community
  • 1
  • 1
thor
  • 21,418
  • 31
  • 87
  • 173
  • 7
    You might like the tuple package, specifically [`Data.Tuple.Curry`](http://hackage.haskell.org/package/tuple-0.3.0.2/docs/Data-Tuple-Curry.html). If your response is, "GROSS!", well, you're not alone. – Daniel Wagner Nov 05 '15 at 19:16
  • 1
    @DanielWagner I laughed. Sometimes I wish tuples were defined as `T a1 (T a2 ..))` with `data T a b = T a !b`, possibly with some ad hoc optimization to recover a good performance. – chi Nov 05 '15 at 19:27
  • Racket's implementation is interesting: http://docs.racket-lang.org/reference/procedures.html?q=curry#%28def._%28%28lib._racket%2Ffunction..rkt%29._curry%29%29 – uselpa Nov 05 '15 at 19:48
  • I've rolled my own `uncurry3` and `uncurry4` functions; I haven't found a need for 5+ yet. – the-konapie Nov 05 '15 at 21:21

1 Answers1

3

If the curry operation is treated as a higher order function, it can't directly apply to f3, because curry expects a function of type (X,Y) -> Z, and the argument of f3 is a triple, not a pair. The same issue arises with a function fn that takes an n-tuple.

There are aspects of your question that include much of the strong typing of Haskell that aren't present in most Lisps. For instance, an easy n-ary curry could be defined as:

(defun curry (function first-argument)
  (lambda (&rest args)
    (apply function first-argument args)))

CL-USER> (let ((f (curry (curry (lambda (x y z)
                                  (* x (+ y z)))
                                2)
                         3)))
           (mapcar f '(1 2 3 4 5)))
; (8 10 12 14 16)
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353