4 ms·
I'm not sure I fully appreciate the distinction you're trying to make here: "currying != partial application". Can you clarify? In particular I don't know what
by brundolf 5y ago
I'm not sure I fully appreciate the distinction you're trying to make here: "currying != partial application". Can you clarify?
In particular I don't know what's meant by "curried" and "uncurried" languages
- djur 5y agoIn Standard ML and Haskell, all functions are curried by default -- they take a single argument, and the syntax for defining multiple-argument functions is just sugar for defining single-argument functions that return single-argument functions. That's reflected in this Haskell type signature for a function adding two integers: add :: Int -> Int -> Int This is a function that takes one integer and returns a function which itself takes another integer and then finally returns an integer. Syntax sugar allows you to define it and call it like a single function. An uncurried function in these languages is a function that takes multiple arguments as a tuple. add :: (Int, Int) -> Int You don't see a lot of functions defined this way in Haskell because there isn't really any advantage to doing so in a lazy, pure language. It's more common in Standard ML from what I've seen, because SML is strict and impure.
- smohare 5y agoAt a deeper level currying is just a specific application of the Hom-tensor adjunction to the category of Sets. In particular the curried function is equivalent to the original. Partial function mappings is a restriction, and inherently not a injection. That is, generally the partial function is not in an equivalent Hom space to the original function.
- DemocracyFTW 5y agoそう言う事ですね〜ッ。は〜い
- masklinn 5y ago> I'm not sure I fully appreciate the distinction you're trying to make here: "currying != partial application". Can you clarify? Currying is the conversion of an n-ary function into a chain of 1-ary function e.g. `fn(a, b, c) -> d` becomes `fn(a) -> fn(b) -> fn(c) -> d`. Partial application is what it says on the tin, it only applies k parameters to the function returning an (n-k) parameters function, without actually running the function. Currying is one method allowing partial application, but not necessarily the only one, or usually the best fit as it tends to not interact well with features like overloading, default parameters, keyword parameters, … > In particular I don't know what's meant by "curried" and "uncurried" languages Languages like Haskell, OCaml, or Elm are "curried" by default: when you define an n-ary function it's really just sugar for a chain of 1-ary functions; and the application of multiple arguments is similarly the implicit application of single arguments multiple times e.g. map : (a -> b) -> List a -> List b map f l = case l of [] -> [] (h::t) -> (f h) :: (map f t) can be called as map fn [1, 2, 3] or (map fn) [1, 2, 3] the semantics are identical, which is not the case in an uncurried language like Javascript or Python: map(fn, [1, 2, 3]) and map(fn)([1, 2, 3]) will behave very differently unless the implementer has taken special steps to handle this case e.g. dynamic behaviour based on an optional second parameter, overloading, etc…
- brundolf 5y ago> applies k parameters to the function returning an (n-k) parameters function, without actually running the function What would be the use of this? Just delaying the execution of the function's side-effects? I'll tip my hand: I'm working on a JS-like (and JS-targeted) language that I want to support partial-application/currying by default. Under the hood everything is represented in a curried way, but syntactically you can both define and invoke/partially-invoke functions with the more familiar syntax (commas). But this is fully superficial right now; it all happens at the parser level. Is there a downside to doing things this way?
- flyingchipmann 5y agoIf you come from typical oop background like java. Imagine there is a function has 5 parameters, and you need to to provide the first 3 first. Then later on you are using this partially applied function somewhere else. You can even reuse it later with different 2 params. Compare to class, it's just like how you initialize an object with certain values, then do something else with this object.
- djur 5y agoThe downside is that curried functions make default, optional, and keyword parameters difficult to implement. For defaults/optionals, given "fn f(x, y, z=10)", if "f(1, 2)" evaluates to "f(1)(2)", does that return a function or the result of "f(1)(2)(10)"? What if you have "fn f(x, y = 10, z)"? All of this is a lot easier if you can evaluate the full argument list at the time of function invocation. As for keyword arguments, they just don't play well with any kind of enforced ordering.
- brundolf 5y agoGot it. I wonder if that ambiguity could be resolved using contextual type info? I.e. if one of the two interpretations fits the expected type, use that. Otherwise, type-error. Maybe that would be confusing, not sure.
- RexM 5y ago