I would go for a split of the currying and proposed solutions. Logically
y = x |> f2(a, _)
y = x |> f2(_, b)
are currying, but the implementation doesn't need to create functions any more than if the _ was %. And
fb = f2(a, _)
fa = f2(_, b)
are explicit currying which would be nice to have at times, but would mostly use in piped context at first, perhaps to give it a more meaningful or narrowed-scope name.
You can curry the second parameter without it being too ugly like this:
half = (`div` 2)
Also, I think the idea with curried languages is that you're supposed to write your functions with the parameter that people are most likely to want to curry first.
That's an interesting idea, but how does it work for functions of multiple arguments?
If functions are curried, then I suppose the syntax for `f x y` would be `y.(x.f)`, which maybe you could write as `y.x.f` if the associativity worked as such. But that means you have to provide your arguments in reverse order?
If functions are not curried, do you write `(x, y).f`?
Firstly, this is definitely partial application not currying (see my other post on this thread for great expansion on this point).
Secondly, this is merely a syntactic item you're looking for. It's trivial to achieve this end in any language with first class anonymous functions. I'm not claiming that syntax isn't important, but instead just pointing out that it really is a trivial transformation to include if it were valuable enough.
> It strikes me as being very useful in combination with the 'apply' functions.
It's very useful with higher-order functions in general. Even more so because most of the languages with operators simply being (binary) infix function calls also default to curried functions[1], which you can easily partially apply.
Haskell also has the reverse operation (MLs probably have it as well) of being able to use a binary function as an operator: "a `foo` b" is equivalent to "foo a b", but sometimes reads much better.
Let's say you have a validation function that matches a string with a given regex, and you need to use that same logic in several places, using a different regex. Currying allows you to write something like this:
validate :: Regex -> String -> T
validate r s = ...
validateIpAddr :: String -> T
validateIpAddr = validate ipRegex
validateZipCode :: String -> T
validateZipCode = validate zipCodeRegex
And so on and so forth. It can reduce boilerplate, and lets you do stuff like map partially applied functions to functors.
I was just thinking about that. You have to do it by hacking the infix syntactic sugar.
x |> f = f x
gives you lambda calculus, but it gets ugly, since you need to specify order of operations with parentheses.
(4 |> (5 |> (+))) |> (3 |> (*))
You can take it a step further with tuples, but you still need to be explicit about the number of arguments:
(x,y) |> f = f x y
((4,5) |> (+), 3) |> (*)
Maybe you could go almost all the way by telling it to create a List when passed two values, and telling it apply to the (nested) List when called with a List and an operator, but off hand, I can't think of a way to get it to type check, particularly not without killing currying.
Is the currying example even currying? It looks like it's just a function returning a function to me. I thought currying it's some thing like func contains(subString: String, string: String) -> Bool, and calling contains("a") would automatically return a func(x: String) -> Bool.
Very nice trick, while using of foo|(bar) is very simple, somehow I don't see such approach being used very often, and it looks like it could simplify a number of things.
let f0 = fun x -> (x, x) in
let f1 = fun y -> f0(f0 y) in
let f2 = fun y -> f1(f1 y) in
let f3 = fun y -> f2(f2 y) in
let f4 = fun y -> f3(f3 y) in
let f5 = fun y -> f4(f4 y) in
f5 (fun z -> z)
reply