Live data from Hacker News

Currying

wiki.haskell.org

31–40 of 134 posts

Re: Currying

#31
post #2

In my entire life as a programmer, this is the one thing that I've found most confusing. Our old codebase used a lot of curried Ramda functions and nobody on the team could read any of it. We spent a week ripping every single instance of it out and replaced it with regular lodash and never looked back and never had an issue with it again. After like ten or fifteen hours of trying to understand what currying is, I sti…

Since you know JavaScript, this should help.

Uncurried:

((x, y) => x * y)(3, 5) === 15

Curried:

(x => y => x * y)(3)(5) === 15

If you don't understand that, your problem is that you don't understand anonymous functions (lambdas), not that you don't understand currying.

Re: Currying

#32
post #4

Earlier quoted context omitted.

Ramda, lodash, no idea what currying is, ... Software is in good hands.

Heh, so much of the world runs on basic business software. If it ran fine after the rewrite, with much less cognitive load, why not? These were just bog standard web pages that someone overengineered the hell out of, to a point that nobody else could understand or maintain it. Sure, that might win them l33t points, but wasn't very useful otherwise.

As a Haskell programmer, I have to agree with you.

When you're writing Haskell, you should write idiomatic Haskell. Currying is part of that. It's a trivial concept and we use it liberally at work. If you're writing JavaScript though, I think it's a different story. I don't think JavaScript lends itself to FP in the way that Haskell or Elm does, and trying to make it do that only makes a project harder to work on.

Re: Currying

#33
Currying is one of those things in Haskell that always makes me think that Haskellers were so preoccupied with whether or not they could, that they didn't stop to think if they should.

In my limited Haskell experience, you can mostly ignore that functions are curried, but every once in a while, someone uses it, and it has never, in my experience, made the code easier to understand, because the currying happens implicitly.

The more general case of currying is partial application, where instead of a function taking only its first argument and returning a function that takes its next argument, you can apply a function any of it's arguments and return a function that takes the remaining arguments. So if you have:

  div x y = x / y
Then:

  invert = (\x -> div 1 x)
  -- invert is a partial application of div to the 1 as first argument
  
  halve = (\x -> div x 2)
  -- halve is a partial application of div to 2 as the second argument
Obviously, the first one could be done with currying. What makes partial application better in my opinion is that it's explicit about what's happening, and doesn't happen without you asking it to.

Re: Currying

#34

When you pass some arguments to a constructor and then later, you pass some more arguments to a method, that’s equivalent to currying. Method calls are easier to read and work better with autocomplete.

I think you confuse currying with partial application.

Are you saying this to be helpful, or just to show you're smarter? If you're saying this to be helpful, you should probably explain more.

Currying is a subset of partial application, so I suspect the person you're responding to is just being a bit loose with their wording, as opposed to not understanding the topic.

Re: Currying

#35

Earlier quoted context omitted.

When I were a lad, elementary school meant four hours of beatings in a muddy field, and we were glad of it

On that note, I found Orwell's posthumously-published Such, Such Were the Joys (about his boarding school days) suggests the inspirations behind large swaths of 1984 .

Coming Up for Air is practically my childhood in a nutshell

Re: Currying

#36

Earlier quoted context omitted.

I think you confuse currying with partial application.

Are you saying this to be helpful, or just to show you're smarter? If you're saying this to be helpful, you should probably explain more. Currying is a subset of partial application, so I suspect the person you're responding to is just being a bit loose with their wording, as opposed to not understanding the topic.

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.

Re: Currying

#37

When you pass some arguments to a constructor and then later, you pass some more arguments to a method, that’s equivalent to currying. Method calls are easier to read and work better with autocomplete.

No, not exactly. And partial application of any function is nowadays possible using anonymous functions to wrap the original one, no need for constructors and special methods.

What currying in Haskell and any other ML does, is the following as Javascript. Let's say we have a function with four parameters `func(a, b, c, d) {return a + b + c + d;}`, then the curried version is the following:

   func = (a) => {
     return (b) => {
       return (c) => {
         return (d) => a + b + c + d;
      } 
     } 
    }

Re: Currying

#38
post #2

In my entire life as a programmer, this is the one thing that I've found most confusing. Our old codebase used a lot of curried Ramda functions and nobody on the team could read any of it. We spent a week ripping every single instance of it out and replaced it with regular lodash and never looked back and never had an issue with it again. After like ten or fifteen hours of trying to understand what currying is, I sti…

In Haskell it is easy. If you "forget" the last argument to a function, you get returned a function where you can provide that later on. A bit like saying "you can fill this in later". That is a "curried" function. Example add 1 2 // add is curried, you can use it like this, the "normal" way, returns 3 p = add 1 // since add is curried I can also provide just the first argument p 2 // and then apply the last argument…

Honestly, a lot of these 'advanced' features aren't a good choice in most codebases IMO. The vast majority of 'enterprise' coding is CRUD and glue, where execution speed doesn't matter and being as simple and explicit as possible is the highest virtue. And the significant number of professional coders who worked hard to get their heads around things like pointers and printf format specifiers are still plenty productive in those kinds of codebases.

Things like currying are fun but like anything that encourages gratuitously deep call trees, they wreck your locality of reference (as a developer) and force you to 'decompile' the code in your head in order to understand it. I'm sure that a top level developer would be able to write curried JS in such a way that it was clear and readable to another top level developer, but that's not the point. The code's not for you, it's for newbie who gets stuck with it when you move on.

Re: Currying

#39
post #2

In my entire life as a programmer, this is the one thing that I've found most confusing. Our old codebase used a lot of curried Ramda functions and nobody on the team could read any of it. We spent a week ripping every single instance of it out and replaced it with regular lodash and never looked back and never had an issue with it again. After like ten or fifteen hours of trying to understand what currying is, I sti…

In Haskell it is easy. If you "forget" the last argument to a function, you get returned a function where you can provide that later on. A bit like saying "you can fill this in later". That is a "curried" function. Example add 1 2 // add is curried, you can use it like this, the "normal" way, returns 3 p = add 1 // since add is curried I can also provide just the first argument p 2 // and then apply the last argument…

I've never liked this "feature".

What if you forget, not in quotes, to give the second argument? Why on earth would you want to get a type error in a completely different part of the code because you got a function instead of an integer? Wouldn't it be desirable to have the compiler just tell you that you forgot the second argument where you forgot the second argument?

Is it really valuable to be able to do:

    p = add 1
...instead of:

    inc = (\x -> add 1 x)
...or, heaven forbid:

    inc x = add 1 x
...?

I mean, I get the idea, they're following the lambda calculus, but this is one of the things that should have been dropped when they started to expand the lambda calculus to a general purpose programming language.

Re: Currying

#40

Earlier quoted context omitted.

I think you confuse currying with partial application.

Are you saying this to be helpful, or just to show you're smarter? If you're saying this to be helpful, you should probably explain more. Currying is a subset of partial application, so I suspect the person you're responding to is just being a bit loose with their wording, as opposed to not understanding the topic.

Currying and partial application are dualities (think of them as function introduction/function elimination), so neither subsumes the other one.

However, I agree with the wording of the original comment: when you _pass_ some arguments to a constructor and then to a method, this is (at least conceptually) partial application.

Post reply on HN