Currying vs partial function application

This is a slightly odd post, and before you read it you should probably put yourself into one of three buckets:

  • Someone who doesn’t care too much about functional programming, and finds higher order functions tricky: feel free to skip this post entirely.
  • Someone who knows all about functional programming, and already knows the difference between currying and partial function application: please read this post carefully and post comments about any inaccuracies you find. (Yes, the CAPTCHA is broken on Chrome; sorry.)
  • Someone who doesn’t know much about functional programming yet, but is interested to learn more: please take this post with a pinch of salt, and read the comments carefully. Read other articles by more experienced developers for more information.

Basically, I’ve been aware for a while that some people use the terms currying and partial function application somewhat interchangably, when they shouldn’t. It’s one of those topics (like monads) which I feel I understand to some extent, and I’ve decided that the best way of making sure I understand it is to try to write about it. If it helps the topic become more accessible to other developers, so much the better.

This post contains no Haskell

Almost every explanation I’ve ever seen of either topic has given examples in a "proper" functional language, typically Haskell. I have absolutely nothing against Haskell, but I typically find it easier to understand examples in a programming language I understand. I also find it much easier to write examples in a program language I understand, so all the examples in this post are going to be in C#. In fact, it’s all available in a single file – that includes all of the examples, admittedly with a few variables renamed. Just compile and run.

C# isn’t really a functional language – I know just about enough to understand that delegates aren’t really a proper substitute for first class functions. However, they’re good enough to demonstrate the principles involved.

While it’s possible to demonstrate currying and partial function application using a function (method) taking a very small number of parameters, I’ve chosen to use 3 for clarity. Although my methods to perform the currying and partial function application will be generic (so all the types of parameters and return value are arbitrary) I’m using a simple function for demonstration purposes:

static string SampleFunction(int a, int b, int c) 

    return string.Format("a={0}; b={1}; c={2}", a, b, c); 
}

So far, so simple. There’s nothing tricky about that method, so don’t look for anything surprising.

What’s it all about?

Both currying and partial function application are about converting one sort of function to another. We’ll use delegates as an approximation to functions, so if we want to treat the method SampleFunction as a value, we can write:

Func<int, int, int, string> function = SampleFunction;

This single line is useful for two reasons:

  • Assigning the value to a variable hammers home the point that it really is a value. A delegate instance is an object much like any other, and the value of the function variable is a reference just like any other.
  • Method group conversions (using just the name of the method as a way of creating a delegate) doesn’t work terribly nicely with type inference when calling a generic method.

We can already call the function using three arguments with no further work:

string result = function(1, 2, 3);

Or equivalently:

string result = function.Invoke(1, 2, 3);

(The C# compiler just converts the shorthand of the first form to the second. The IL emitted will be the same.)

That’s fine if we’ve got all the arguments available at the same time, but what if we haven’t? To give a concrete (if somewhat contrived) example, suppose we have a logging function with three parameters (source, severity, message) and within a single class (which I’ll call BusinessLogic for the moment) we always want to use the same value for the "source" parameter, and we’d like to be able to log easily everywhere in the class specifying just the severity and message. We have a few options:

  • Create an adapter class which takes the log function (or more generally a logging object) and the "source" value in its constructor, stashes both in instance variables, and exposes a method with two parameters. That method just delegates to the stashed logger, using the source it’s remembered to supply the first argument to the three-parameter method. In BusinessLogic we create an instance of the adapter class, and stash a reference in an instance variable – then just call the two-parameter method everywhere we need to. This is probably overkill if we only need the adapter from BusinessLogic, but it’s reusable… so long as we’re trying to adapt the same logging function.
  • Store the original logger in our BusinessLogic class, but create a helper method with two parameters. This can hard-code the value used for the "source" parameter in one place (the helper method). If we need to do this in several places, it gets annoying.
  • Use a more general functional programming approach – probably partial function application in this case.

I’m deliberately ignoring the discrepancy between holding a reference to "the logger" and holding a reference to "the logging function". Obviously there’s a significant difference if we need to use more than one function from the logging class, but for the purposes of thinking about currying and partial function application, we’ll just think of "a logger" as "a function taking three parameters" (like our sample function).

Now that I’ve given the slightly-real-world concrete example for a bit of motivation, I’m going to ignore it for the rest of the post, and just talk about our sample function. I don’t want to write a whole BusinessLogic class which pretends to do something useful; I’m sure you can perform the appropriate mental conversion from "the sample function" to "something I might actually want to do".

Partial Function Application

The purpose of partial function application is to take a function with N parameters and a value for one of those parameters, and return a function with N-1 parameters, such that calling the result will assemble all the required values appropriately (the 1 argument given to the partial application operation itself, and the N-1 arguments given to the returned function). So in code form, these two calls should be equivalent for our 3-parameter method:

// Normal call
string result1 = function(1, 2, 3);

// Call via partial application
Func<int, int, string> partialFunction = ApplyPartial(function, 1); 
string result2 = partialFunction(2, 3);

In this case I’ve implemented partial application with a single parameter, and chosen the first one – you could write an ApplyPartial method which took more arguments to apply, or which used them somewhere else in the final function execution. I believe that picking off parameters one at a time, from the start, is the most conventional approach.

Thanks to anonymous functions (a lambda expression in this case, but an anonymous method wouldn’t be much more verbose), the implementation of ApplyPartial is simple:

static Func<T2, T3, TResult> ApplyPartial<T1, T2, T3, TResult>
    (Func<T1, T2, T3, TResult> function, T1 arg1) 

    return (b, c) => function(arg1, b, c); 
}

The generics make the method look more complicated than it really is. Note that the lack of higher order types in C# means that you’d need a method like this for every delegate you wanted to use – if you wanted a version for a function which started with four parameters, you’d need an ApplyPartial<T1, T2, T3, T4, TResult> method etc. You’d probably also want a parallel set of methods for the Action delegate family.

The final thing to note is that assuming we had all of these methods, we could perform partial function application again – even potentially down to a parameterless function if we wanted, like this:

Func<int, int, string> partial1 = ApplyPartial(function, 1); 
Func<int, string> partial2 = ApplyPartial(partial1, 2); 
Func<string> partial3 = ApplyPartial(partial2, 3); 
string result = partial3();

Again, only the final line would actually invoke the original function.

Okay, so that’s partial function application. That’s relatively straightforward. Currying is slightly harder to get your head round, in my view.

Currying

Whereas partial function application converts a function with N parameters into a function with N-1 parameters by applying one argument, currying effectively decomposes the function into functions taking a single parameter. We don’t pass any arguments into the Curry method itself:

  • Curry(f) returns a function f1 such that…
  • f1(a) returns a function f2 such that…
  • f2(b) returns a function f3 such that…
  • f3(c) invokes f(a, b, c)

(Again, note that this is specific to our three-parameter function – but hopefully it’s obvious how it would extend to other signatures.)

To give our "equivalence" example again, we can write:

// Normal call
string result1 = function(1, 2, 3);

// Call via currying
Func<int, Func<int, Func<int, string>>> f1 = Curry(function); 
Func<int, Func<int, string>> f2 = f1(1); 
Func<int, string> f3 = f2(2); 
string result2 = f3(3);

// Or to do make all the calls together…
var curried = Curry(function); 
string result3 = curried(1)(2)(3);

The difference between the latter examples shows one reason why functional languages often have good type inference and compact representations of function types: that declaration of f1 is pretty fearsome.

Now that we know what the Curry method is meant to do, it’s actually surprisingly simple to implement. Indeed, all we need to do is translate the bullet points above into lambda expressions. It’s a thing of beauty:

static Func<T1, Func<T2, Func<T3, TResult>>> Curry<T1, T2, T3, TResult> 
    (Func<T1, T2, T3, TResult> function) 

    return a => b => c => function(a, b, c); 
}

If you want to add some brackets to make it clearer for you, feel free – personally I think it just adds clutter. Either way, we get what we want. (It’s worth thinking about how annoying it would be to write that without lambda expressions or anonymous methods. Not hard, just annoying.)

So that’s currying. I think. Maybe.

Conclusion

I can’t say I’ve ever knowingly used currying, whereas I suspect some bits of Noda Time‘s text parsing effectively use partial functional application. (If anyone really wants me to dig in and check, I’ll do so.)

I really hope I’ve got the difference between them right here – it feels right, in that the two are clearly related, but also quite distinct. Now that we’ve reached the end, think about how that difference manifests itself when there are only two parameters, and hopefully you’ll see why I chose to use three :)

My gut feeling is that currying is a more useful concept in an academic context, whereas partial functional application is more useful in practice. However, that’s the gut feeling of someone who hasn’t really used a functional language in anger. If I ever really get round to using F#, maybe I’ll do a follow-up post. For now, I’m hoping that my trusty smart readers can provide useful thoughts for others.

41 thoughts on “Currying vs partial function application”

  1. +1, this is completely right. It’s great to see this content on a popular blog. The level of ignorance around the distinction between the two is staggering, especially in the JavaScript community.

    Like

  2. Currying is extremely useful as an abstraction for libraries, because it removes the annoying arity problem when writing code that’s supposed to abstract over functions of any number of parameters. It may be that you don’t see the use for it because you haven’t been able to use it.

    Consider trying to write a generic “Memoize” function; it should take in a function of N parameters, and return a function of N parameters which checks a cache before calling the original argument. How would you do that in C#? You’d have to take either of two approaches: limit yourself to some sensible N and write approximately the same Memoize function, overloaded for each arity; or use reflection and perhaps Reflection.Emit to get back the performance loss.

    But if your functions are curried, there is no such thing as variable arity for your functions. All functions have exactly one argument. They are trivial to memoize.

    Like

  3. Yes, I like the composition vs decomposition approach and the gist of feels right to me as well :)
    But it looks ugly in C#. Using a more functional language such as Scala makes the ugly angle brackets disappear…

    Like

  4. A few rambling thoughts:

    – both ApplyPartial and Curry (in your sense) are side-effect free. This matters, because it means that ApplyPartial(f,x) is almost equivalent to Curry(f)(x). Essentially, whether you write f(x,y) or f(x)(y) is just syntactic sugar, even in a language like C#: nothing actually happens until the final parameter is provided anyhow.

    – therefore, ApplyPartial and Curry aren’t exactly the same, but I don’t see the big conceptual difference – it’s mostly just syntactic sugar. Using ApplyPartial Curry is trivially emulated by replacing function application with ApplyPartial, and vice versa, ApplyPartial can be trivially emulated with Curry by calling the returned function with parameters in sequence rather than all at once.

    – In essence though, minus some details, ApplyPartial(f,x) is like Curry(f)(x); for two-parameter its exactly the same. Conversely, you could think of Curry(f) as ApplyPartial(ApplyPartial, f)

    So in summary, isn’t currying just the notion of passing parameters consecutively (with the necessary types) in general and partial application the notion of passing parameters consecutively with the specific case that the first parameter’s already been defined?

    Like

  5. I’m not an expert in functional programming, but I think you got it right… Actually, I don’t think the difference between currying and partial application is difficult at all to understand; both concept might look similar if you’ve never used a functional language, but it becomes quite obvious as soon as you do.

    BTW, have you noticed how the C# implementation of currying looks similar to the way function signatures are written in most functional languages? For instance, Func would be written as a -> b -> c -> d in Haskell…

    Like

  6. Couple of corrections to the article:

    * Method group conversions (using just the **same** of the method
    * You call f3(1) when discussing currying, in line with your previous examples I believe that should be f3(3)?

    Like

  7. @Barry: the traditionally, obvious memoize wouldn’t work with curried functions. After all, you’d implement a memoize that caches the return value for any given parameter value – but that return value is just the partially applied function, and memoizing it isn’t saving any expensive computation, just the construction of an object (to store the parameter).

    You’d need a memoize that was return-type aware, and would work as usual when returning non function values, but would memoize returned functions recursively.

    Like

  8. After some more thought, I think this distinction (between currying and partial function application) isn’t the one I’d highlight. Instead, I think of it this way: Partial function application is a _technique_ for simplifying function calls later on by specifying known parameter values now. In contrast, currying is a more general approach to always pass all parameters in sequential function applications; it’s what you’d get when you try to generalize partial function application.

    Also, the sequential nature of curried arguments bears emphasis: whereas it’s common enough to partially apply other arguments than the first and the order of the arguments doesn’t really matter, the same can not be said for curried functions. That means that it’s quite important to get the argument order “right” in a functional API since it’s a hassle reordering parameters. In that sense partial function application is a better fit for non-functional languages since the API is likely not to be curried-function friendly.

    e.g. LINQ: functions like Select and Where take the list as the first parameter. So if I’d curry them and pass one argument, that’d let me fix the _data_ they process. But wouldn’t it make more sense to fix the function? i.e. aren’t you more likely to need a function EvenNumbers which is Where x % 2 ==0 than a function Filter1to20? For this reason, functional languages will generally pass the filter or mapping function first, and then the data, rather than the LINQ API’s order.

    And that’s points to a real fundamental problem in functional languages. By putting the “least changing” argument first, you undermine autocompletion, which is a really nifty tool for API discovery. I’m not sure what’s best here, but it’s definitely a loss, particularly since otherwise the functional technique lends itself so clearly to pipe-and-filter style programming, where you just kind-of define what you need and go with what you have now: exploratory programming which would benefit from Intellisense a lot.

    Like

  9. @Barry: Perhaps more relevant to this post, it allows you do partial application like this:

    Curry(f)(1)

    You simply apply the Curried function to the argument you want to apply.

    Like

  10. I’d put it this way: Partial function application is practically useful only if the functions you are calling /are/ already in curried form (or: curried functions make partial application straightforward). Because in functional languages, we almost always write functions in curried form (i.e. in pseudo-C# x => y => x + y instead of (x,y) => x + y), partial application “just works,” you don’t even have to think about it. Only explicitly “tupled” functions need to be uncurried before partial application. Now in C# (and Java and …) it’s just the other way round as almost all functions/methods/… are tupled and hence partial application just isn’t really useable.

    Like

  11. @Eamon – “the traditionally, obvious memoize wouldn’t work with curried functions” – of course it would. The traditional memoize would construct a key composed from the arguments and look it up in a dictionary; memoize applied to a curried function stretches out the construction of the key over each partial application. It’s not until the final argument that you to “save computation”, but that’s the very beauty of it: the memoize function doesn’t need to know that, and doesn’t need to care about the distinction – in other words, it *doesn’t need* to be “return-type aware”.

    It’s true that the dictionary constructed will look more like a trie rather than a hash table (each successive partial application will be navigating down a level in the trie, and each level in the trie will be dedicated to a parameter), but many fast dictionaries are built that way too.

    Like

  12. “Now that we know what the Curry method is meant to do, it’s actually surprisingly simple to implement. Indeed, all we need to do is translate the bullet points above into lambda expressions. It’s a thing of beauty:”

    I would say it’s simple to implement in C# in the one specific case of a 3-arg function. How would you write this for the general case?

    The standard way for a .NET library seems to be to implement it 5 times, for each of 1-5 arguments. (Or is it 16 now?)

    I think you could do it, with more difficulty, by taking a function and reflecting to determine the number of items, but I don’t think I see a type-safe way to do it in C#.

    Like

  13. @Jane: No, you can’t do it in a statically typed way in general in C#. That’s what we get for C# being a more “primitive” language in terms of using delegates instead of richer function types, as I understand it.

    Like

  14. You can’t really write curry in a statically typed way in general in ML or Haskell either. The Haskell prelude definition only works for pairs. I believe you’d need dependent types for such a thing (or at least lots of GHC language extension abuse).

    Like

  15. No expert either, but my understanding was pretty much the same as Frank’s: if your function isn’t curried (it’s tupled), you have to curry it, and then you can partially apply. Not sure that that’s 100% right though. Where’s Tomas when you need him? :)

    Like

  16. @Frank: I agree. I thought it made sense to quote the ‘Real-World Functional Programming’ book by Petricek with Skeet:

    “A term that you can sometimes hear when using the partial function
    application is currying. This refers to converting a function that takes multiple arguments (as a tuple) into a function that takes the first argument and returns a function taking the next argument, and so on. So, for example, the function of type int -> int -> int is a curried form of a
    function that has a type (int * int) -> int. Partial function application
    is then the use of a curried function without specifying all the arguments.”

    Like

  17. @Barry:

    If the memoization is simple because it only needs deal with functions of arity 1, to me that suggests it’s not doing anything complicated and in particular is not considering further arguments. E.g. it’s an implementation like this:

    Func Memoize(Func func) {
    var cache = new ConcurrentDictionary();
    return arg => cache.GetOrAdd(arg, func);
    }

    And a memoizer like that is not going to do anything useful for curried (multi-argument) functions.

    So unless I’m missing something you can either curry an already memoized function (but then you’ve got the issue of dealing with a variable number of arguments), or you can memoize an already curried function in a return-type aware fashion (more complex & needs fancier type system or reflection to choose between either functions that return functions and those that do not, but at least you avoid tons of overloads), or you memoize an already curried function without regards to the fact that the function is curried (and then your memoization doesn’t do much).

    Like

    1. Think of it as “dependency injection” for FP.

      Instead of having a one-trick-pony of a class, with a single “do-the-work” method, and the configuration in its constructor, the configuration values are passed in as the first few parameters to a function. The partially applied versions of the function become “configured instances” and/or “interface implementations”, in effect.

      Yes, you can do this with classes. But it takes more code (WET), and you have to decide ahead of time which parameters go to the constructor(s) and which goes to the “method” (or its overloaded versions). In the FP version, you just write a single function (DRY) with the “least volatile” parameters first and the “most volatile” parameters last. Then, you “inject” whatever configuration you want into the original function to make a new function with a shorter argument list.

      Like

  18. @tobi: You’d have to ask a functional programmer. I can’t say I’ve ever needed currying in C#. I suspect I’ve used partial function application a few times though – or at least something very similar, just not explicitly called out as that.

    Like

  19. Sure, using it explicity using lambdas calling other lambdas happens. You don’t need/want the combinator for that, though.

    Like

  20. A long time ago in C++ the STL came into being. It had beautiful algorithms that could clearly express intent in a single line of code. But **wail** it was painful to use, because all you had where function objects (classes like delegates), and you had to write new ones all the time to apply your functions (equality comparers, actions etc) into their algorithms.

    Then one day boost::bind (also known as partial application) shamelessly wandered in after mistaking C++ for a functional language, and his mate lambda followed soon after – and then the STL was usable !!

    So i would suggest in C# that if your using lambda’s, and LINQ methods, or the static algorithm like methods on Array or List that you’ve got the use of partial application nailed.

    To currying – I do find the two confusing, and think this is a great topic, but wonder if it’s useful outside of haskell/functional languages. In haskell all functions are curried – alledgedly ***to enable partial function application***. More thinking required, or compiler knowledge to know why that is so. So if you can use partial application, and currying is the default why would anyone need to know about it ? It’s because in haskell when the args are passed in one go, it’s as a tuple, and you may need to curry it (convert to single args) to be able to better use partial application.

    I think the explanation misses the mark a bit because your original sample function is uncurried (default in C#) but you CAN use partial application on it. Others are alluded to in the haskell wiki.

    PS: Great line – “So far, so simple. There’s nothing tricky about that method, so don’t look for anything surprising.” very helpful when a potentially tricky article requires scrutinising every line !

    PPS: Apologies for including haskell in your non haskell post !

    Liked by 1 person

  21. You said “My gut feeling is that currying is a more useful concept in an academic context, whereas partial function[] application is more useful in practice.”

    It gets more interesting when partial evaluation is added to the mix. Partial evaluation can give you some big performance boosts. For example, my Paint.NET effects (http://users.telenet.be/krisvandermotten/Downloads/PaintDotNetEffects.html) get their performance using partial evaluation.

    For more information, also see http://blogs.u2u.net/kris/post/2010/05/24/Lambda-Curry.aspx

    Like

  22. To me the essential difference is this:

    With partial function application the function implementation that is eventually executed when all arguments have been specified is always the same.

    With currying it is possible to return different “partially applied” functions depending on the values of the earlier arguments. This allows you to precompute/cache stuff that only depends on the earlier arguments and thus optimize for repeated applications of the “partially applied” curried function.

    For example, currying allows you define a parseRegex function with the signature

    let parseRegex: pattern -> (stream -> result)

    This parseRegex function could return a specialized parser function with the signature stream -> result depending on the specified pattern. For example (parseRegex “d+”) would return a specialized function just for parsing a decimal number. This specialized parser function could then be repeatedly applied to the input stream without having to repeat work that was done in the first step.

    Like

  23. @Stephan: Currying is not the same as partial evaluation, also known as function specialization. But indeed, partial evaluation requires currying, or, currying opens the door to partial evaluation.

    Partial application as presented here does not allow that.

    Like

  24. Jon, don’t get me wrong, I respect you, but something here does not compute. You are the coathour of the “Real World Functional Programming: With Examples in F# and C#” (2010), and 2 years later you admit that you don’t fully grasp difference between partial application of the function and currying. So how you were able to write that book?

    Like

  25. @macias: As I say in the book, I did very little of the writing – I mostly edited the language, and challenged Tomas on some of the C# bits. My F# is virtually non-existent, unfortunately.

    And I think I now *do* properly grasp the difference :)

    Like

  26. Let me tell what is the situation in Haskell. In Haskell, all functions take precisely one argument; the type of functions taking a and returing b is a -> b, for example Int -> String is a function taking an integer and returning a string. And Int -> (Char -> String) is a function that takes an integer, and returns a function that takes a character, and returns a string. There are *no* multiparameter functions at all, unlike C languages. Signature of a function, as in mathematics, is a single domain and codomain.

    However, a function of type Int -> (Char -> String) can be thought of taking two parameters, integer and character, and returning a string. This is technically false – as all functions take only one parameter – but it is a very convenient lie, and no one has problems with this. Such pseudo-multiparameter functions are very common, and -> type operator associates to right, so the same type is written Int -> Char -> String, without parenthesis.

    Now, if you have function F of that type, you can compute F(5)(‘a’) and get a string. But you can also compute F(2) and get a function. The latter is called “partial application”. Simply speaking, “partial application” occurs when you have a function A -> (B -> C) and apply it to get a function B -> C, but do not give another argument yet to get a value of type C. Partial application is technically a normal application, and there is nothing special about it. It’s only a fancy name if you do not “apply enough arguments” to a function that returns a function. For example, if you apply only one argument n to addition, you get incrementation operator that increments input by n.

    There is also another way you could simulate multivariate functions, by taking tuples. For example, (Int, Char) -> String is a function that takes a tuple of integer and char, and returns a string. It is very different from previous example. You cannot do partial application trick as previously – you have to specify the integer and character at once. However, you can convert between (Int, Char) -> String and Int -> (Char -> String). Going right is called currying, and the function Int -> (Char -> String) is called curried; going left is called uncurrying, and the function that takes a tuple is called uncurried.

    In fact there are higher order polymorphic functions that convert between those two.

    curry :: ((a,b) -> c) -> a -> b -> c

    uncurry :: (a -> b -> c) -> (a,b) -> c

    So “partial application” is a fancy name when you use a function returning a function… but do not feed the resulting function another argument, as done in most cases.

    This description gets more complicated in C# because you can have functions that really take multiple arguments, unlike Haskell where all functions technically take one argument (which is sometimes a tuple).

    Suppose there are X elements of type A, Y elements of type B, and Z elements of type C. Then there are exactly Y^X functions from A to B (a.k.a. combinations). Since currying and uncurrying are invertible, there are as many curried as uncurried functions:

    Z^(X*Y) = (Z^X)^Y

    This is the well known exponent law! Other exponent laws also have manifestations as invertible transformations on types.

    Liked by 1 person

  27. In class terms:

    “Partial class”:

    class TextWriter
    {
    private string prefix;

    TextWriter( string prefix )
    {
    this.prefix = prefix;
    }

    public void Write( string str )
    {
    Console.WriteLine( prefix + str );
    }
    }

    “Currying class”

    class TextWriter
    {
    private StreamWriter streamWriter;

    TextWriter( StreamWriter streamWriter )
    {
    this.streamWriter = streamWriter;
    }

    public void Write( string str )
    {
    streamWriter.WriteLine( str );
    }
    }

    Like

  28. I’m not convinced this is 100% correct. Whenever I’ve read about partial function application elsewhere it has always been defined as calling a function with less than the full number of arguments — anywhere from n – 1 to n – (n – 1) — whereas you describe it as calling a function with n – 1 arguments.

    Also, though I understand the point in using C# to explain it because it is a language people understand, and because that is what you blog is about, explaining it in C# gives the impression that it is far more awkward and strange than it is. Even in a job as a code monkey churning out javascript to link buttons on a webpage to click handlers, I found myself using partial function application so that multiple user interface elements could make use of the same partially applied function. In C# doing this would be sufficiently awkward that you would inevitably end up achieving the same thing in a different way, e.g. by having a named function that called your main function with particular arguments.

    Like

  29. @James: Partial function application doesn’t call the function immediately at all. I’ve described the situation where you provide a function with n parameters along with one argument and end up with a function with n – 1 parameters… but I explicitly stated that the partial function application could take a different number of arguments to partially apply.

    I wrote this in C# so that I’d be convinced I’d understand my own code and thoughts – which wouldn’t be the case if I’d tried using Haskell, F# etc. Whether or not C# is ideally suited to partial function application is entirely separate from whether I’ve described it correctly.

    Like

  30. I misused the word “call”, I should have said “pass arguments to” or “fix”. Certainly I cannot claim to be an expert when I misuse basic terminology! However, you open your piece on partial function application by stating:

    “The purpose of partial function application is to take a function with N parameters and a value for one of those parameters, and return a function with N-1 parameters”.

    It is true a couple of sentences later you went on to say:

    “you could write an ApplyPartial method which took more arguments to apply”

    but your opening statement seems to state that the returned function always returns n – 1 parameters. I am not doubting your understanding (which is very likely better than my own), only your wording. Anyway, all of this is further confused by the fact that in functional languages like F# etc, all functions are in fact curried into a chain of functions with a single parameter, with multiple argument functions being syntactic sugar.

    And I am not saying it is wrong to explain the concept using C#, I am just pointing out that if someone who knew nothing about functional programming read this then the use of C# might make the concept seem more unwieldy and esoteric than it really is.

    Like

  31. @sdcvvc
    If that’s correct (and I have no reason to doubt it – I just dont know haskell), that is a brilliant explanation. You should write a book!

    Like

Leave a comment