1

I was reading a blog post about combining higher order functions and it provided a C# example of "currying".

The examples look like:

public static Func<T1, Func<T2, T3>> Curry<T1, T2, T3>
    (Func<T1, T2, T3> function) 
{ return a => b => function(a, b); }

public static Func<T1, Func<T2, Func<T3, T4>>> Curry<T1, T2, T3, T4>
    (Func<T1, T2, T3, T4> function)
{ return a => b => c => function(a, b, c); }

public static Func<T1, Func<T2, Func<T3, Func<T4, T5>>>> Curry<T1, T2, T3, T4, T5>
    (Func<T1, T2, T3, T4, T5> function) 
{ return a => b => c => d => function(a, b, c, d); }

My question is, can methods taking other forms that effectively produce the same "curried form" result be considered currying.

For example, are the following methods considered currying? If not, what is the more appropriate naming convention?

public static Func<T1, Func<T2, Func<T3, Func<T4, T5>>>> SomethingLikeCurry<T1, T2, T3, T4, T5>
    (Func<T1, T2, Func<T3, T4, T5>> function) 
{ return a => b => c => d => function(a, b)(c, d); }

public static Func<T1, Func<T2, Func<T3, T4>>> SomethingLikeCurry<T1, T2, T3, T4>
    (Func<T1, T2, Func<T3, T4>> function) 
{ return a => b => c => function(a, b)(c); }
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
smartcaveman
  • 41,281
  • 29
  • 127
  • 212
  • Pretty sure that's still currying. It's not a single currying operation, it's multiple currying operations, but currying is still what you're doing. – Servy Jun 06 '13 at 20:37
  • 1
    I think the answer is yes, but this question is probably better suited for http://programmers.stackexchange.com/ – p.s.w.g Jun 06 '13 at 20:37
  • @p.s.w.g - it seems in scope to me - I would think that if this isn't considered currying, that developers who use functional languages probably have a term to refer to this. In general, terminological questions have been considered on topic ( e.g. http://stackoverflow.com/questions/521893/whats-the-best-name-for-a-non-mutating-add-method-on-an-immutable-collection ) – smartcaveman Jun 06 '13 at 20:42
  • @Servy, does a further distinction need to be made when the currying operations occur at a "nested level"? e.g. `Func>` would only require one currying operation to be in curried form, but it has to happen at what I am referring to as a "nested level" – smartcaveman Jun 06 '13 at 20:45
  • @smartcaveman I'd be rather surprised to find a name for that exact situation. I'd say what you're doing *is* currying, and you're also invoking (perhaps there's a more appropriate term here) one function to access the inner function, and once you do that it's just normal currying. So you're doing currying plus something else, rather than just doing some entirely new thing. – Servy Jun 06 '13 at 20:49
  • 1
    It is certainly in the spirit of currying. I'd have no problem calling any of these currying. – Eric Lippert Jun 06 '13 at 21:17
  • It is currying by composing currying operations. – kqr Jun 06 '13 at 22:18
  • @kqr - will you post that comment as an answer so i can select it please – smartcaveman Jan 17 '14 at 20:39

1 Answers1

0

From wikipedia

.. currying is the technique of transforming a function that takes multiple arguments (or a tuple of arguments) in such a way that it can be called as a chain of functions, each with a single argument ...

So are the two methods you've asked about currying functions? Let's simplify their declarations for easy inspection:

Func<T1, T2, Func<T3, T4, T5>>  => Func<T1, Func<T2, Func<T3, Func<T4, T5>>>>
^ multiple arguments               ^ all single arguments 
Func<T1, T2, Func<T3, T4>>      => Func<T1, Func<T2, Func<T3, T4>>>
^ multiple arguments               ^ all single arguments

So, the answer is yes; these are currying functions.

Please note: this would not have been a correct currying function signature:

Func<T1, T2, Func<T3, T4, T5>>  => Func<T1, Func<T2, Func<T3, T4, T5>>>>

As the output of the function is not a chain of functions, each with a single argument. Therefore having only a simpler weak typed currying signature like this

Func<T1, T2, TResult>           => Func<T1, Func<T2, TResult>>

does not produce currying when the result TResult is a function with multiple arguments. The two methods that triggered your interest are simply there to prevent this from happening for functions with one or two arguments. Of course, in the curried version type T5 may also be a function that has multiple arguments, therefore we would could on and on ad infinitum.

Lodewijk Bogaards
  • 19,777
  • 3
  • 28
  • 52