A simple question about the dotted pair as an argument in a curry function

A simple question about the dotted pair as an argument in a curry function

Post by Joe Arden » Tue, 27 Feb 2007 18:52:40


Hello, I've been trying to figure out why the following code needs to
be thus:

(define curry
(lambda (f . x)
(lambda (y)
(apply f (append x (list y))))))

RATHER THAN (note the signature of the first lambda):

(define curry
(lambda (f x)
(lambda (y)
(apply f (append x (list y))))))

It's frustrating, because I feel like the understanding is *almost
there*. The answer must be simple, yet it remains elusive. The
feeling is most powerful when contemplating http://www.yqcomputer.com/ #./binding:h2
(the section immediately before 4.3), yet enlightenment is not
forthcoming. Finally, I have swallowed my pride, and come here asking
for a clue. Can you provide? My eternal gratitude goes to you if you
can :)
 
 
 

A simple question about the dotted pair as an argument in a curry function

Post by Jussi Piit » Tue, 27 Feb 2007 19:35:20

Joe Ardent writes:


This lets you call a procedure of at least one argument with all the
arguments but last, and then to supply the last one to the result:

(curry * 3 2 1) ==> (lambda (y) (* 3 2 1 y))
((curry * 3 2 1) 0) ==> (* 3 2 1 0)


This lets you call a procedure of at least one argument with a list of
all but last, and then to supply the last one to the result:

(curry * (list 3 2 1)) ==> (lambda (y) (* 3 2 1 y))
((curry * (list 3 2 1)) 0) ==> (* 3 2 1 0)

If you knew the number of arguments, you wouldn't play with the dot,
apply and append at all:

(define curry
(lambda (f x y z)
(lambda (w)
(f x y z w))))

(curry * 3 2 1) ==> (lambda (w) (* 3 2 1 w))
((curry * 3 2 1) 0) ==> (* 3 2 1 0)

(curry * 3 2) ==> ???

 
 
 

A simple question about the dotted pair as an argument in a curry function

Post by Joe Arden » Wed, 28 Feb 2007 19:14:31

On Feb 26, 11:35 pm, Jussi Piitulainen < XXXX@XXXXX.COM >


Ah, ha! The vague notion I had was a low-level muttering along the
lines of,
"It automatically list-i-fies the formal arguments and allows you to
use the car (f)
and cdr (x) without having to say so." Which I suppose is one way to
look at it,
even if it's not the most correct way?


There's the money; thank you for reformulating the function to point
out how you'd
make it simpler (less functional), highlighting the reasoning behind
using a
dotted pair in the original version. Jussi Piitulainen, you have my
eternal
gratitude! As does "pbwig", who replied in private, and also pointed
out the
utility of "reverse curry", which enables you to say:

(define halve (rev-curry / 2))

AND/OR

(define 2x (rev-curry * 2))

and have it work as you'd naively expect. Thank you both!
 
 
 

A simple question about the dotted pair as an argument in a curry function

Post by Jan Skibin » Fri, 02 Mar 2007 10:19:21

n Feb 26, 5:35am, Jussi Piitulainen < XXXX@XXXXX.COM >
wrote:

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
exactly
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
Haskell).

I will start the discussion with the following two definitions, taken
from
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
parentheses
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
argument.

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
this macro.
;; --------
;; 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.
;;
(define-syntax curry
(syntax-rules()
((curry 0 f) f)
((curry 1 f) ((x1)
(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)
(f x1
 
 
 

A simple question about the dotted pair as an argument in a curry function

Post by Graha » Sat, 03 Mar 2007 04:42:09


Are you aware of SRFI-26, "Notation for Specializing Parameters
without Currying"? It's not currying, but serves a similar purpose.

http://www.yqcomputer.com/

Graham
 
 
 

A simple question about the dotted pair as an argument in a curry function

Post by Jan Skibin » Sat, 03 Mar 2007 06:52:13


Yes, I am -- as I am aware about its goals and its critique ("not
general enough") on the related mailing list. It is hard to make
everyone happy. :-)

My post here was not a SRFI proposal, just a pedagogical attempt to
explain what I understand by "true" function curry in the simplest
possible terms: a transformation from the uncurried representation to
the curried one.

I do not expect anyone to use "curry" the way I have shown. But I use
it, often in combination with a "place holder operator" ? as a
shortcut when supplying operators to higher order function, such as
filter, map, sum, etc.
Jan