Earlier quoted context omitted.
As noted in the article: > This feature does have some limitations, for instance when we have multiple nested function calls, but in those cases an explicit lambda expression is always still possible. I've also complained about that a while ago https://news.ycombinator.com/item?id=35707689 --- The solution is to delimit the level of expression the underscore (or dollar sign suggested in the article) belongs to. In Ko…
I think I like the explicit lambda better; I prefer to be judicious with syntactic sugar and special variable names. fun x => add(subtract(x, 2), 3) // Virgil
A case against currying
81–90 of 135 posts
Re: A case against currying
#82Earlier quoted context omitted.
Let us postulate two functions. One is named foobinade, and it takes three arguments. The other is named foobinadd, and it only takes two arguments. (Yes, I know, shoot anybody who actually names things that way.) When someone writes f = foobinade a b g = foobinadd c d there is no confusion to the compiler. The problem is the reader . Unless you have the signatures of foobinade and foobinadd memorized, you have no wa…
> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…
Re: A case against currying
#83I couldn't agree more. Having spent a lot of time with a language with currying like this recently, it seems very obviously a misfeature. 1. Looking at a function call, you can't tell if it's returning data, or a function from some unknown number of arguments to data, without carefully examining both its declaration and its call site 2. Writing a function call, you can accidentally get a function rather than data if…
That's not the case with Haskell.
Haskell has a tendency to pick up features that have deep theoretical reasoning and "mathematical beauty". Of course, that doesn't always correlate with codebase health very well either, and there's a segment of the community that is very vocal about dropping features because of that.
Anyway, the case here is that a superficial kind of mathematical beauty seems to conflict with a deeper case of it.
Re: A case against currying
#84Same for imperative languages with "parameter list" style. In python, with
def f(a, b): return c, d
def g(k, l): return m, n
you can't do
f(g(1,2))
but have to use
f(*g(1,2))
what is analogical to uncurry, but operate on value rather than function.
TBH I can't name a language where such f(g(1,2)) would work.
Re: A case against currying
#85Earlier quoted context omitted.
Let us postulate two functions. One is named foobinade, and it takes three arguments. The other is named foobinadd, and it only takes two arguments. (Yes, I know, shoot anybody who actually names things that way.) When someone writes f = foobinade a b g = foobinadd c d there is no confusion to the compiler. The problem is the reader . Unless you have the signatures of foobinade and foobinadd memorized, you have no wa…
> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…
Everyone knows that. At least everyone who would click a post titled "A case against currying." The article's author clearly knows that too.
That's not the point. The point is that this distinction is very meaningful in practice, as many functions are only meant to be used in one way. It's extremely rare that you need to (printf "%d %d" foo). The extra freedom provided by currying is useful, but it should be opt-in.
Just because two things are fundamentally equivalent, it doesn't mean it's useless to distinguish them. Mathematics is the art of giving the same name to different things; and engineering is the art of giving different names to the same thing depending on the context.
Re: A case against currying
#86Re: A case against currying
#87[1]: https://gavinhoward.com/2025/04/how-i-solved-the-expression-...
Re: A case against currying
#88Earlier quoted context omitted.
> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…
Fine, it's a regular type. It's still not the type I think it is . If it's an Int -> Int when I think it's an Int, that's still a problem, no matter how much Int -> Int is an "actual result".
let f :: Int = foobinade a b
And the compiler immediately tells you that you are wrong: your type annotation does not unify with compiler’s inferred type.And if you think this is verbose, well many traditional imperative languages like C have no type deduction and you will need to provide a type for every variable anyways.
Re: A case against currying
#89Earlier quoted context omitted.
Let us postulate two functions. One is named foobinade, and it takes three arguments. The other is named foobinadd, and it only takes two arguments. (Yes, I know, shoot anybody who actually names things that way.) When someone writes f = foobinade a b g = foobinadd c d there is no confusion to the compiler. The problem is the reader . Unless you have the signatures of foobinade and foobinadd memorized, you have no wa…
> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…
Re: A case against currying
#90Earlier quoted context omitted.
Let us postulate two functions. One is named foobinade, and it takes three arguments. The other is named foobinadd, and it only takes two arguments. (Yes, I know, shoot anybody who actually names things that way.) When someone writes f = foobinade a b g = foobinadd c d there is no confusion to the compiler. The problem is the reader . Unless you have the signatures of foobinade and foobinadd memorized, you have no wa…
> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…