I have twice recently refactored code in order to change the order of parameters because there was too much code where hacks like flip
or \x -> foo bar x 42
were happening.
When designing a function signature what principles will help me to make the best use of currying?
An example would be ADD : ADD(1,2) and ADD(2,1) can be used interchangeably, the order of parameters does not matter.
Higher-order functions are functions that take functions as parameters or return functions when called. Curried functions are higher-order functions that take one argument at a time returning a series of functions until all parameters are passed.
In other terms, currying is when a function — instead of taking all arguments at one time — takes the first one and returns a new function, which takes the second one and returns a new function, which takes the third one, etc. until all arguments are completed.
Currying is helpful when you have to frequently call a function with a fixed argument. Considering, for example, the following function: If we want to define the function error , warn , and info , for every type, we have two options. Currying provides a shorter, concise, and more readable solution.
For languages that support currying and partial-application easily, there is one compelling series of arguments, originally from Chris Okasaki:
Why? You can then compose operations on the data nicely. E.g. insert 1 $ insert 2 $ insert 3 $ s
. This also helps for functions on state.
Standard libraries such as "containers" follow this convention.
Alternate arguments are sometimes given to put the data structure first, so it can be closed over, yielding functions on a static structure (e.g. lookup) that are a bit more concise. However, the broad consensus seems to be that this is less of a win, especially since it pushes you towards heavily parenthesized code.
For recursive functions, it is common to put the argument that varies the most (e.g. an accumulator) as the last argument, while the argument that varies the least (e.g. a function argument) at the start. This composes well with the data structure last style.
A summary of the Okasaki view is given in his Edison library (again, another data structure library):
Place the arguments that you are most likely to reuse first. Function arguments are a great example of this. You are much more likely to want to map f
over two different lists, than you are to want to map many different functions over the same list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With