question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

curry2 :: ((a, b) -> c) -> a -> b -> c

See original GitHub issue

Now that Sanctuary is close to being an alternative to Ramda rather than a library intended to be used alongside it, we should consider which Ramda functions we would miss were we to remove Ramda from our projects. R.curry and R.curryN are certainly important functions. def performs currying, of course, but not every project which depends on Sanctuary also depends on sanctuary-def.

The type signatures of these Ramda functions are misleading:

curry  :: (* -> a) -> (* -> a)
curryN :: Number -> (* -> a) -> (* -> a)

Accurate type signatures are an important tool for reasoning about functions. The Sanctuary functions would be much simpler:

curry2 :: ((a, b) -> c) -> a -> b -> c
curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
curry4 :: ((a, b, c, d) -> e) -> a -> b -> c -> d -> e
curry5 :: ((a, b, c, d, e) -> f) -> a -> b -> c -> d -> e -> f

We must choose the maximum supported arity. I don’t think it’s necessary to go all the way to curry5; curry2 and curry3 should suffice. If you call recall using R.curry or R.curryN to produce a function of arity greater than 3, please speak up.

🍛

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:1
  • Comments:20 (16 by maintainers)

github_iconTop GitHub Comments

3reactions
davidchamberscommented, Nov 13, 2016

Right now, I feel like the path to learning FP in JS involves [these steps]

Good point, @EvanBurchard. “FP in JS” is just part of the functional programming journey, though. Ideally people will go from Underscore to Ramda to Sanctuary to PureScript to Haskell to Idris and beyond (while pursuing other wonderful approaches such as Lisp). 😄

The more concessions we make in order for Sanctuary to seem familiar to Underscore and Ramda users, the less familiar PureScript and Haskell will seem to Sanctuary users.

One day I’d love to hear a story about a team that had used Ramda, adopted Sanctuary for increased type safety, used it successfully for some time, then realized they could write the same sort of code in PureScript and thus replace their run-time type checking with compile-time type checking.

3reactions
davidchamberscommented, Nov 13, 2016

Is there an issue with a general curryN and liftN that I’m missing? They seem to be very helpful functions, and they aren’t variadic. I guess the return types aren’t really well defined without using dependent types or something like that though.

Well-defined output types are just as important to me as well-defined input types. One could argue that input-dependent output types are idiomatic in a language as dynamic as JavaScript, and there are many libraries—such as Ramda—which cater to those who agree. I have a different viewpoint. There is no compiler to scour our programs for errors, so the onus is on us as programmers to reason about the types of the values flowing through our programs. This makes it even more important to use simple functions which are explicit about arity (at the very least). It’s clear that curry2(f) will evaluate to a value of type * -> * -> *. What is the shape of R.curry(f)? We can’t know without determining the arity of f. A Ramda-style curry is ever so slightly more convenient than curry2, as it saves us one keystroke, but the loss of clarity is a more significant concern.

Another concern is implementation complexity. The Ramda team has shown a willingness to accept complex implementations in order to provide the desired API. With complexity come edge cases. With edge cases come bugs. Again, because we have no support from a compiler it’s important that we rely on functions we can reason about. There’s a striking difference in complexity between the implementations of R.liftN and Z.lift2.

Especially with curry, I do find myself currying functions with 4 parameters or more on occasion, though not too often.

That’s enough for me. Let’s provide curry2, curry3, curry4, and curry5.

I’m not super opinionated on this, as lately I’ve been just manually currying by determining how many parameters I will want to initially pass in, and then returning a function that takes the remaining parameters.

I’ve done this dance many times before. I appreciate the fact that Ramda-style currying saves me from having to choose one of the following types (for some quaternary function):

  • f :: a -> b -> c -> d -> e
  • f :: a -> b -> ((c, d) -> e)
  • f :: a -> ((b, c) -> (d -> e))
  • f :: a -> ((b, c, d) -> e)
  • f :: (a, b) -> (c -> d -> e)
  • f :: (a, b) -> ((c, d) -> e)
  • f :: (a, b, c) -> (d -> e)
  • f :: (a, b, c, d) -> e

Although Ramda-style currying is at odds with my preference for well-defined types (as a function can have all the above types at once), I like to view f(x, y) as syntactic sugar for f(x)(y) for some Ramda-style curried function f.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Boolean Algebra
Design a logic circuit with three inputs A, B, C and one output F such that F=1 only when a majority of the...
Read more >
Currying - The Modern JavaScript Tutorial
Currying is a transformation of functions that translates a function from callable as f(a, b, c) into callable as f(a)(b)(c) .
Read more >
Manually doing function body-substitution to see how a ...
So that, in pseudocode, ((curry 1 f) a ...) == (f a ...) (((curry 2 f) a) b ...) == (f a b...
Read more >
EOPL-1 - Rose-Hulman
However, the expression (a b c) is a procedure call whose value depends on the values of the variables a, b, and c;...
Read more >
Simplify ABC+AB'C+A'BC+A'B'C+A'B'C' - Math Stack Exchange
I think that the true answer is C+A′B′ and not C+A′B as you suggest. You did well, but could go on with: C+A′B′C′=(C+A′B′)(C+C′)=C+A′B′....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found