Talk:Partial function application

From Rosetta Code
Revision as of 20:26, 14 April 2011 by rosettacode>Kernigh (The update is OK with me. Java solution.)

Explicit curry vs Partial application

In Python there is a clear difference. Here's explicit currying:

<lang python>def fsf1(fs, f1):

   return lambda s: fs(f1, s)</lang>

I would like to tie this task down, but now recognise that it may be difficult.

Any programmers, especially those with functional as well as none functional language experience care to comment? --Paddy3118 02:28, 26 March 2011 (UTC)

With Common Lisp, the explicit currying seems to be the only way to do the partial application. I try to show this with code. This is mapcar with 2 arguments.
<lang lisp>CL-USER> (defun f1 (n) (* n 2))

F1 CL-USER> (mapcar #'f1 '(2 3 5 7)) (4 6 10 14)</lang>

I can use lambda for the explicit currying, like one would in Python.
<lang lisp>CL-USER> ((lambda (s) (mapcar #'f1 s)) '(2 3 5 7))

(4 6 10 14)</lang>

I can also define a partial function for the partial application; but it uses the explicit currying to do so.
<lang lisp>CL-USER> (defun partial (f &rest args)

(lambda (&rest args2) (apply f (append args args2)))) PARTIAL CL-USER> (funcall (partial #'mapcar #'f1) '(2 3 5 7)) (4 6 10 14)</lang>

There is not much reason to write (partial #'mapcar #'f1) instead of (lambda (s) (mapcar #'f1 s)). This would be like writing sum((2, 3)) instead of 2 + 3 in Python. --Kernigh 02:34, 1 April 2011 (UTC)
Is it the case that there is no real distinction in Lisp, but a significant distinction in other languages?
What about the other feature I seem to see in partial application: that of not needing to refer explicitely to the other arguments of the function being partially applied? E.g. with function f(a,b,c,d); you can partial(f, a=value1) to produce f'(b,c,d) without mention of b, c, and d when calling partial. --Paddy3118 06:29, 1 April 2011 (UTC)
First considering the feature of not referring to other arguments, I would expect this to be possible in most languages with dynamic types, but not possible in languages with static type checking. Kernigh's partial handles this just fine using apply, for example. This document I found calls it generalized explicit currying and gives example code in Scheme. In Go, with it's static type checking, I can write a partial that does explicit currying for functions with specific type signatures, but I can't write a partial that does generalized explicit currying for functions with arbitrary type signatures.
Which leads back to the first question of the distinction between (partial #'mapcar #'f1) and (lambda (s) (mapcar #'f1 s)). There are two distinctions! Function/lambda expression and generalized/specific. (And they are orthogonal: You could write a specific function or a generalized lambda expression.) Anyway, there seems little point in either a function or generality in the case of this task as currently written. You could just write fsf1 = lambda s: fs(f1, s) in Python, for example.
As far as changes to the task, I think it's fine the way it is. —Sonia 06:28, 13 April 2011 (UTC)
Hi. Ocaml and Haskell are statically typed and yet don't seem to need to mention the other arguments. At this stage, I want a task that fits the page title so am trying to explore what partial function application could mean for many languages. --Paddy3118 07:00, 13 April 2011 (UTC)
If not mentioning the other args. was made a task restriction, could it then be done in Go? --Paddy3118 07:04, 13 April 2011 (UTC)
Touché. If not mentioning the other args was made a task restriction, I'm pretty sure it could not be done in Go. Go requires static typing yet has no way of specifying one function type in terms of another function type. It might be a good restriction. Simple closures are already demonstrated in tasks like Function composition and First class functions. I might reword it "Note that in the partial application of a parameter, (in the above case param1), the only inputs are f and param1. The return value and arguments of f' are determined solely by f and are not explicitly mentioned. This is an essential feature of partial function application." I might also remove "( s )" from task bullets 4 and 5, so that they read just "Partially apply f1 to fs to form function fsf1." It's a little more cryptic, but it removes a possible suggestion that it's okay to specify the argument list of fsf1. —Sonia 18:32, 13 April 2011 (UTC)
Thanks Sonia. Anyone else OK with such an update? (Remember, the idea isn't to exclude Go; it is to more explicitely define partial application). --Paddy3118 21:08, 13 April 2011 (UTC)
The update is OK with me.
I used (partial #'fs #'f1) to solve Common Lisp. I also solved Java. Java is a statically typed language, so the solution is like Ocaml or Haskell: I have to curry the fs() method. I start with this Java code.
<lang java>static int[] fs(IntegerFunction f, int[] s) {

int[] r = new int[s.length]; for (int i = 0; i < s.length; i++) r[i] = f.call(s[i]); return r; }

static int[] fsf1(int[] s) { return fs(f1, s); }</lang>

This fsf1() explicitly curries fs(), mentions s and passes the return value from fs(). I change the code.
<lang java>interface SequenceFunction {

int[] call(int[] arg); }

static SequenceFunction fs(final IntegerFunction f) { return new SequenceFunction() { public int[] call(int[] s) { int[] r = new int[s.length]; for (int i = 0; i < s.length; i++) r[i] = f.call(s[i]); return r; } }; }

static SequenceFunction fsf1 = fs(f1);</lang>

This fs() explicitly curries itself. So fsf1 never has to mention s nor pass the return value from fs(). --Kernigh 20:26, 14 April 2011 (UTC)