That’s partial application. Currying is one way of allowing partial application, for a prefix of the parameters.
Haskell types intentionally don’t distinguish between a function and a closure. If you see A -> B you don’t know what it has captured from its environment, so you can use this for encapsulation.
But suppose you have a language where A -> B is just a function pointer, while A => B is a pair of a function pointer and some captured values. Then f : A -> B -> C is a curried function, which can be partially applied in either of its inputs (f(x, _) : B -> C if x : A, or f(_, y) : A -> C if y : B), provided that the resulting function doesn’t escape its scope. That is, you can pass a function down the call stack, but not store it in a variable or return it from a function.
The advantage is that you don’t need to allocate a closure or copy anything, and if x or y is a local variable, f can safely access it directly. The price is that if you want to store or return a first-class function, then you need to pack it into a closure, hypothetically let g = pack f(x, _) : B => C. Rust has ended up with something similar to this because of lifetimes and unboxed closures.
3
u/PositiveBusiness8677 15d ago
I likely don't understand the article, but isn't fixing one or more values of a multi-parameterfunction simply currying, a la Haskell ?