- 
                Notifications
    
You must be signed in to change notification settings  - Fork 33
 
Description
Description
It's annoying when I can't write a function point-free style just because I cannot partially apply the second argument of a 2-ary function (or more generally, the ith parameter of an n-ary). For example, we need the lift function in Functor just because we can't partially apply the function in map in a convenient and easy way.
I propose a new syntax for partial application that extends the current one to allow partial application of any parameters in a function.
Sample usage
I propose to add a new operator <|, that takes a function as first argument and a tuple with values and placeholders as second argument. The placeholders (a placeholder is two underscores) help determine what parameter a value is being applied to.
For partial application of the first parameter, we can also keep the current simplified syntax.
let f: (String, Int) -> Int = { s, i in i }
// Partially apply first argument
let p1CurrentSyntax /* : (Int) -> Int */    = f <| "a"
let p1NewSyntax     /* : (Int) -> Int */    = f <| ("a", __)
// Partially apply second argument
let p2              /* : (String) -> Int */ = f <| (__, 1)Note how I've written the resulting function type in comments, meaning that type inference works well with the syntax.
I chose to reverse the direction and parameter position of the current |> because now the position of the function and the tuple of arguments resembles the order in which you normally write function application.
Potential implementation
The trick is to define a special PlaceHolder type just so we can write .__ on our tuples.
If we also define __ as a global value we can avoid the leading dot. This is not needed (type inference also works if we write .__). It makes the syntax nicer, but it pollutes the global namespace. What do you think?
public enum PlaceHolder {
    case __
}
public let __ = PlaceHolder.__
infix operator <| : AdditionPrecedence
// Support for simplified syntax for partial application of the first parameter
public func <|<A, B, C>(_ f: @escaping (A, B) -> C, _ value: A) -> (B) -> C {
    { b in f(value, b)}
}
public func <|<A, B, C>(_ f: @escaping (A, B) -> C, _ values: (PlaceHolder, B)) -> (A) -> C {
    { a in f(a, values.1)}
}
public func <|<A, B, C>(_ f: @escaping (A, B) -> C, _ values: (A, PlaceHolder)) -> (B) -> C {
    { b in f(values.0, b)}
}
// ... implementations for higher aritiesModules
Bow
Breaking changes
None, unless we remove |>.