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 HaskellAlmost 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.
Read more: Jon Skeet: Coding Blog
QR:
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 HaskellAlmost 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.
Read more: Jon Skeet: Coding Blog
QR:
0 comments:
Post a Comment