n Feb 26, 5:35am, Jussi Piitulainen < XXXX@XXXXX.COM >
I have looked before at many different definitions of "curry"
in Scheme and I must admit that I am confused: they all seem to
be something entirely different from what I know from Haskell.
The confusion is, I think, in mixing curry/uncurry terminology.
To explain what I mean, please indulge me and follow my line of
reasoning for a while...
I will show that currying in Scheme can be made almost as painless
as in Haskell and that a fully curried Scheme function "f" behaves
as a Haskell function - some stylistic differences notwithstanding.
Curried expressions will be given in one of two versions:
parenthesized (in Scheme tradition) and juxtaposed (almost as in
I will start the discussion with the following two definitions, taken
Haskell's Prelude, but decorated with extra parentheses for clarity:
curry :: ((a b) -> c) -> (a -> (b -> c))
uncurry :: (a -> (b -> c)) -> ((a b) -> c)
[Arrows associate to the right, so we could have saved some
by representing (a -> (b -> c)) as (a -> b -> c)]
What it means is this: curry takes an input function to an output
function, where the input function::((a b) -> c) accepts a tuple of
arguments (a b) producing result of type c, and the output
function::(a -> (b -> c)) accepts one argument of type a producing a
funtion of type (b -> c). Uncurry provides the reverse conversion.
Let's extend those Haskell-like definitions by admiting tuples longer
than two: (a b c), (a b c d), (a b c d e) up to some artificial limit
of tuple length, six say.
Formally, we are defining here several families of curry
(Haskell defines just curry-2):
curry-2 :: ((a b) -> c) -> (a -> (b -> c))
curry-3 :: ((a b c) -> d) -> (a -> (b -> (c -> d)))
curry-4 :: ((a b c d) -> e) -> (a -> (b -> (c -> (d -> e)))), etc.
Let's call them "curry" of rank 2, 3, 4, etc. The macro "curry n f"
accepts such rank "n" as the first argument. Note however that all
functions curried this way have arity 1; that is, they accept only one
As could be seen from the implementation of macro "curry" below, the
macro "(curry n f)" wraps an ordinary Scheme function "f" of any
arity in "n" layers of lambdas -- thus converting it to a curried
function of arity "1" and rank "n". This is not the same as a
partial application of a number "n" to a function "f", as some
definitions of curry found in some other sources might imply.
;; syntax: (curry n f)
;; Convert a function "f" of arity "m" into a function
;; accepting one argument a time, where "n" specifies a curry rank.
;; If f is finite (no optional arguments) then "n" must be equal "m",
;; otherwise it can be any natural number. In either case, however,
;; "n" should not exceed the (artificial) limit of 6, supported by
;; I am positive that this macro can be generalized to any arity,
;; but I present it here with such limitation (of 6) just for clarity.
((curry 0 f) f)
((curry 1 f) ((x1)
((curry 2 f) ((x1)((x2)
(f x1 x2))))
((curry 3 f) ((x1)((x2)((x3)
(f x1 x2 x3)))))
((curry 4 f) ((x1)((x2)((x3)((x4)
(f x1 x2 x3 x4))))))
((curry 5 f) ((x1)((x2)((x3)((x4)((x5)