Live data from Hacker News

A case against currying

emi-h.com

41–50 of 135 posts

Re: A case against currying

#41
One "feature of currying" in Haskell that isn't mentioned in the fine article is that parts of the function may not be dependent on the last argument(s) and only needs to be evaluated once over many application of the last argument(s) which can be very useful when partially applied functions are passed to higher-order functions.

Functions can be done explicitly written to do this or it can be achieved through compiler optimisation.

Re: A case against currying

#42
post #30

I like currying because it's fun and cool, but found myself nodding along throughout the whole article. I've taken for granted that declaring and using curried functions with nice associativity (i.e., avoiding lots of parentheses) is as ergonomic as partial application syntax gets, but I'm glad to have that assumption challenged. The "hole" syntax for partial application with dollar signs is a really creative alterna…

Someone else in the comments mentioned that scala does this with _ as the placeholder.

Re: A case against currying

#43
post #2

What benefit does drawing a distinction between parameter list and single-parameter tuple style bring? I'm failing to see how they're not isomorphic.

Presumably creating a different class for parameter lists allows you to extend it with operations that aren't natural to tuples, like named arguments.

Re: A case against currying

#44
The article lists two arguments against Currying:

  1) "performance is a bit of a concern"
  2) "curried function types have a weird shape"
2 is followed by single example of how it doesn't work the way the author would expect it to in Haskell.

It's not a strong case in my opinion. Dismissed.

Re: A case against currying

#45
post #32

Earlier quoted context omitted.

Well, I totally disagree with this. One of the main benefits of currying is the ability to chain function calls together. For example, in F# this is typically done with the |> operator: let result = input |> foobinade a b |> barbalyze c d Or, if we really want to name our partial function before applying it, we can use the >> operator instead: let f = foobinade a b >> barbalyze c d let result = f input Requiring an e…

You can still do this though: let result = (barbalyze(c, d, $) . foobinade(a, b, $)) input Or if you prefer left-to-right: let result = input |> foobinade(a, b, $) |> barbalyze(c, d, $) Maybe what isn't clear is that this hole operator would bind to the innermost function call, not the whole statement.

Even better, this method lets you pipeline into a parameter which isn't the last one:

  let result = input
    |> add_prefix_and_suffix("They said '", $, "'!")

Re: A case against currying

#46
There are good ideas in functional languages that other languages have borrowed, but there are bad ideas too: currying, function call syntax without parentheses, Hindley-Milner type inference, and laziness by default (Haskell) are experiments that new languages shouldn’t copy.

Re: A case against currying

#47
post #2

What benefit does drawing a distinction between parameter list and single-parameter tuple style bring? I'm failing to see how they're not isomorphic.

It's not that they are meaningfully different. It's just acknowledging if you really want currying, you can say 'why not just use a single parameter of tuple type'.

Then there's an implication of 'sure, but that doesn't actually help much if it's not standar' and then it's not addressed further.

Re: A case against currying

#50
post #18
post #9

I'd got a step further and say that in business software, named parameters are preferable for all but the smallest functions. Using curried OR tuple arg lists requires remembering the name of an argument by its position. This saves room on the screen but is mental overhead. The fact is that arguments do always have names anyway and you always have to know what they are.

I want to agree, but there is the tension that in business code, what you pass as arguments is very often already named like the parameter, so having to indicate the parameter name in the call leads to a lot of redundancy. And if you’re using domain types judiciously, the types are typically also different, hence (in a statically-typed language) there is already a reduced risk of passing the wrong parameter. Maybe th…

OCaml has a neat little feature where it elides the parameter and variable name if they're the same:

  let warn_user ~message = ... (* the ~ makes this a named parameter *)

  let error = "fatal error!!" in
  warn_user ~message:error; (* different names, have to specify both *)

  let message = "fatal error!!" in
  warn_user ~message; (* same names, elided *)
The elision doesn't always kick in, because sometimes you want the variable to have a different name, but in practice it kicks in a lot, and makes a real difference. In a way, cases when it doesn't kick in are also telling you something, because you're crossing some sort of context boundary where some value is called different things on either side.
Post reply on HN