Skip to content

Instantly share code, notes, and snippets.

@kristopherjohnson
Last active March 3, 2022 16:11
Show Gist options
  • Save kristopherjohnson/4ee565cfcdf912deacf6 to your computer and use it in GitHub Desktop.
Save kristopherjohnson/4ee565cfcdf912deacf6 to your computer and use it in GitHub Desktop.
Experiments with partial function application in Swift
func partial<A, B, T>(f: (A, B) -> T, a: A) -> (B) -> T {
return { f(a, $0) }
}
func bind2nd<A, B, T>(f: (A, B) -> T, b: B) -> (A) -> T {
return { f($0, b) }
}
func partial<A, B, C, T>(f: (A, B, C) -> T, a: A) -> (B, C) -> T {
return { f(a, $0, $1) }
}
func partial<A, B, C, T>(f: (A, B, C) -> T, a: A, b: B) -> (C) -> T {
return { f(a, b, $0) }
}
func partial<A, B, C, D, T>(f: (A, B, C, D) -> T, a: A, b: B, c: C) -> (D) -> T {
return { f(a, b, c, $0) }
}
func partial<A, B, C, D, T>(f: (A, B, C, D) -> T, a: A, b: B) -> (C, D) -> T {
return { f(a, b, $0, $1) }
}
func partial<A, B, C, D, T>(f: (A, B, C, D) -> T, a: A) -> (B, C, D) -> T {
return { f(a, $0, $1, $2) }
}
// pipe-forward operator used in examples
operator infix |> { associativity left }
func |> <A, B>(a: A, f: A -> B) -> B {
    return f(a)
}
// Numeric examples
func add(a: Int, b: Int) -> Int { return a + b }
func subtract(a: Int, b: Int) -> Int { return a - b }
let addOneTo = partial(add, 1)
let subtractFromOne = partial(subtract, 1)
let subtractOneFrom = bind2nd(subtract, 1)
addOneTo(10) // 11
subtractOneFrom(10) // 9
subtractFromOne(10) // -9
100 |> addOneTo |> addOneTo // 102
// String examples
func join2(a: String, b: String) -> String {
return a + b
}
func join3(a: String, b: String, c: String) -> String {
return a + b + c
}
join2("Hello, ", "world!") // "Hello, world!"
join3("1", "2", "3") // "123"
let prependHello = partial(join2, "Hello, ")
prependHello("Dolly") // "Hello, Dolly"
let appendWorld = bind2nd(join2, "World!")
appendWorld("Goodbye, ") // "Goodbye, World!"
let prependFirstSecond = partial(join3, "First ", "Second ")
prependFirstSecond("Third") // "First Second Third"
let prependFirst = partial(join3, "First ")
prependFirst("Second ", "Third") // "First Second Third"
func bracket(prefix: String, suffix: String, s: String) -> String {
return prefix + s + suffix
}
"Hello" // "<div><p>Hello</p></div>"
|> partial(bracket, "<p>", "</p>")
|> partial(bracket, "<div>", "</div>")
@kristopherjohnson
Copy link
Author

It seems like I should be able to implement at least one of the <A, B, C, T> partials in terms of the <A, B, T> partial, but I can't figure out the necessary syntax/declarations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment