45 ms·
I don't read it that way, no. Currying is a process to transform a function that takes multiple arguments into higher order functions that take one argument at
by whilenot-dev 3y ago
I don't read it that way, no. Currying is a process to transform a function that takes multiple arguments into higher order functions that take one argument at a time to enable partial application (as written in the article). The partial application of a function is a different transformation of a function.
Some languages provide partial application without currying a function - JavaScript has bind, Python has functools.partial etc.
- kerkeslager 3y agoOkay, I understand what you're saying, and you're right, but you're missing my point and doubling down on the same mistake again. Language is inherently imprecise and communication is never perfect. When people say something, it's rude to assume they are wrong or don't understand something because they don't say it exactly the way you would have said it. This is extremely common in technical communication and it's extremely counterproductive. I'm suggesting that you could be a better reader by trying to understand what people are trying to say even if they don't communicate it exactly the way you want them to. For example, no one in this comment chain is confused about what currying or partial application are, so it's a bit rude that you've assumed people are confused because you didn't take the time to figure out what people were trying to communicate. Instead, because people didn't say things exactly the way you would have said it, you jumped in with corrections. If you take a step back and resist the urge to correct people, can you understand how "Currying is a subset of partial application" is true?
- whilenot-dev 3y ago> ...can you understand how "Currying is a subset of partial application" is true? It isn't true and i can understand why someone would make that statement. Currying and partial application both come from a functional mindset that treats functions as data, and like data also functions can be transformed. Currying and partial application both satisfy a transformation depending on a desired context: - Currying "widens" a function "up" (as in you don't need to know all arguments beforehand in the same context anymore) - Partial application "narrows" a function "down" (as in arguments are contained within the context of the partially applied function) "Currying is a subset of partial application" is true in the same sense as if "subtraction is a subset of addition". Sure, you can subtract negative values to have addition and add negative values to have subtraction, but that can't be your point, is it? > If you take a step back and resist the urge to correct people... Please keep it on topic.
- kerkeslager 3y ago> It isn't true and i can understand why someone would make that statement It is true, and you are smart enough to understand it if you stop assuming you're the only one who understands the topic. I'm specifically sticking with the wording "Currying is a subset of partial application" to make the point that you can understand what someone is trying to say even if they don't say it exactly the way you would like them to say it. > - Currying "widens" a function "up" (as in you don't need to know all arguments beforehand in the same context anymore) > - Partial application "narrows" a function "down" (as in arguments are contained within the context of the partially applied function) So you're saying that I'm "widening" the function "up" when I do: increment = add 1 invert = div 1 ...? But I'm "narrowing" the function "down" when I do: increment = (\x -> add 1 x) halve = (\x -> div x 2) ...? When I curry `add` above, isn't the argument 1 contained within the context of the partially applied function? When I partially apply `div` above, don't I no longer have to know all the arguments (i.e. I no longer need to know the denominator 2)? It sure seems like this up/down wide/narrow wording you're fixated on isn't a particularly better descriptions of what's going on with currying and partial application. It mean, maybe it's just my font, but the partial applications are a bit wider on my screen. ;P > "Currying is a subset of partial application" is true in the same sense as if "subtraction is a subset of addition". Sure, you can subtract negative values to have addition and add negative values to have subtraction, but that can't be your point, is it? I'm not sure I understand that analogy to say it's my point. Are you saying you would behave condescendingly toward someone who said "subtraction is a subset of addition" too? > Please keep it on topic. The topic skybrian started was derailed when you decided to "correct" him because you didn't make any effort to understand what he was trying to say. Your behavior is the topic now because your behavior became a problem.
- whilenot-dev 3y agoNeither of your examples does curry a function. The first one partially applies it (the Haskell way), the second one wraps the partial application in a redundant lambda (Haskell again). I think that's where the confusion is, let me also try to use the Haskell syntax... This is an add function with two arguments: add :: (Int, Int) -> Int add (x, y) = x + y At the moment it can not be partially applied, so let's curry it: -- addCurr :: Int -> Int -> Int addCurr = curry add Now let's partially apply it for an increment function: -- increment :: Int -> Int increment = addCurr 1 > When I curry `add` above, isn't the argument 1 contained within the context of the partially applied function? You didn't curry it, you partially applied it. This was possible, because your function add was already curried.
- whilenot-dev 3y ago> no one in this comment chain is confused about what currying or partial application are I can't agree here either... I know it from my own experience when i first learned about currying and partial application.
- kerkeslager 3y agoIt does not appear to me that skybrian is first learning about currying and partial application, and I'm not first learning about currying or partial application in this thread either. Your play at humility that you didn't understand currying and partial application in the past kinda falls flat if you then go on to less-humbly assume that everyone else in the conversation is stuck where you once were.
- electrondood 3y agoYou seem to be reacting to your own assumption that the original response was making an assumption. I understood it instead to be generalizing to a related concept, and inferred no condescension, FWIW.
- threatofrain 3y agoI thought it was somewhat the reverse — that the original motivation was to simulate multi-arity functions in a setting that only allows unary functions.
- bPspGiJT8Y 3y agoI don't really understand the distinction between "multi-arity" and "unary" functions. In my mental model, all functions are unary, it's just that in "traditional", non-FP languages it's more common to pack arguments into tuples. That is `(a, b, c) => ...` in JS is a unary function which takes a tuple of 3 items. But the thing is, FP has tuples too (and in Haskell, with pretty much the same syntax), it's just that most of the time arguments aren't packed into tuples. So could you elaborate to me where the distinction lies here and why is there a need to "simulate" things?
- jraph 3y agoSay you are dealing with a callback mechanism that takes a function and (only) one value to pass: function c(f, v) { ... f(v) ... } But what you actually need this callback mechanism to call is a function that takes two arguments. No default values. function f2(a, b) { ... } There's no way in js that c is going to call f2 and set its b parameter to something. You can't set v to be a tuple so b will be filled: c(f2, "value") => b will be undefined. c(f2, [1, 2]) => a will be set to [1, 2]. you need to wrap f2 for this when calling c: function wrapf2(b) { return f2("fixed a", b) } Or you can make c deconstruct v, or use apply: function c(f, v) { ... f(...v) ... } function c(f, v) { ... f.apply(null, v) ... } but then v always needs to be an array: c(f, [1]) c(f, [1, 2]) c(f, 1) // fails This is why in Javascript, multi-arity is different from unary with tuples. JS doesn't have tuples as a primitive / first-class type anyway. In some math notations we don't make the difference, but in most programming languages there's a distinction. Your model where functions are always unary but can take tuples, and (v) is the same as v, is correct (and useful when the distinction doesn't matter and is just annoying to deal with), but doesn't match the way many programming languages actually work. I believe even in most functional programming languages, (v) is different from v, you also said it. In assembly, different parameters are in fully separate registers or stack entries. Interestingly, you could imagine representing tuples as C structs (that can have only one member) and always pass structs, and passing a one-member struct will actually have the exact same effect as passing a value of a primitive type.