Remix.run Logo
twic 6 hours ago

I 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 you leave off an argument; coupled with pervasive type inference, this can lead to some really tiresome compiler errors

3. Functions which return functions look just like functions which take more arguments and return data (card-carrying functional programmers might argue these are really the same thing, but semantically, they aren't at all - in what sense is make_string_comparator_for_locale "really" a function which takes a locale and a string and returns a function from string to ordering?)

3a. Because of point 3, our codebase has a trivial wrapper to put round functions when your function actually returns a function (so make_string_comparator_for_locale has type like Locale -> Function<string -> string -> order>), so now if you actually want to return a function, there's boilerplate at the return and call sites that wouldn't be there in a less 'concise' language!

I think programming languages have a tendency to pick up cute features that give you a little dopamine kick when you use them, but that aren't actually good for the health of a substantial codebase. I think academic and hobby languages, and so functional languages, are particularly prone to this. I think implicit currying is one of these features.

tikhonj 3 hours ago | parent | next [-]

> in what sense is make_string_comparator_for_locale "really" a function which takes a locale and a string and returns a function from string to ordering?

In the sense that "make_string_comparator" is not a useful concept. Being able to make a "string comparator" is inherently a function of being able to compare strings, and carving out a bespoke concept for some variation of this universal idea adds complexity that is neither necessary nor particularly useful. At the extreme, that's how you end up with Enterprise-style OO codebases full of useless nouns like "FooAdapter" and "BarFactory".

The alternative is to have a consistent, systematic way to turn verbs into nouns. In English we have gerunds. I don't have to say "the sport where you ski" and "the activity where you write", I can just say "skiing" and "writing". In functional programming we have lambdas. On top of that, curried functions are just a sort of convenient contraction to make the common case smoother. And hey, maybe the contraction isn't worth the learning curve or usability edge-cases, but the function it's serving is still important!

> Because of point 3, our codebase has a trivial wrapper to put round functions when your function actually returns a function

That seems either completely self-inflicted, or a limitation of whatever language you're using. I've worked on a number of codebases in Haskell, OCaml and a couple of Lisps, and I have never seen or wanted anything remotely like this.

marcosdumay 3 hours ago | parent | prev [-]

> I think programming languages have a tendency to pick up cute features that give you a little dopamine kick when you use them, but that aren't actually good for the health of a substantial codebase.

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.

Blikkentrekker an hour ago | parent [-]

I always felt Monads were an utterly disgusting hack that was otherwise quite practical though. It didn't feel like mathematical beauty at all to me but like a hack to fool to the optimizer to not sequence out of events.