Last active
March 17, 2020 23:32
-
-
Save daveyostcom/21cc630c3431026db73abd7606a59414 to your computer and use it in GitHub Desktop.
partial function application vs currying
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Consider the heavily-aligned source code as a kind of exploded view to aid understanding. | |
// C# version: https://gist.github.com/daveyostcom/307aedf294042d0aba596cda9cc480ea | |
// Swift version: https://gist.github.com/daveyostcom/21cc630c3431026db73abd7606a59414 | |
// Inspired by https://codeblog.jonskeet.uk/2012/01/30/currying-vs-partial-function-application/ | |
class PartialFunctionApplicationVsCurrying { | |
func main() { | |
// Call the function directly. | |
print("\(function(1, true, "3")) – normal call") | |
// Call via partial application, binding arg by arg. | |
var partial1 = applyPartial(function, p1: 1) | |
var partial2 = applyPartial(partial1, p2: true) | |
var partial3 = applyPartial(partial2, p3: "3") | |
print("\(partial1( true, "3")) – partial application, binding a1") | |
print("\(partial2( "3")) – partial application, binding a1,a2") | |
print("\(partial3( )) – partial application, binding a1,a2,a3") | |
// Call via partial application, binding a1,a2 then a3. | |
var partial4 = applyPartial(function, p1: 1, p2: true) | |
var partial5 = applyPartial(partial2, p3: "3") | |
print("\(partial4( "3")) – partial application, binding a1,a2 at once") | |
print("\(partial5( )) – partial application, binding a1,a2,a3") | |
// Call via currying, arg by arg. | |
var curried1: (Int) -> (Bool) -> (Character) -> String = curry3(function) | |
var curried2: (Bool) -> (Character) -> String = curried1(1) | |
var curried3: (Character) -> String = curried2 (true) | |
var curried4: String = curried3 ("3") | |
print("\(curried4) – currying, in three stages") | |
// Call all stages at once. | |
var curried5: String = curried1(1)(true)("3") | |
print("\(curried5) – currying, all at once") | |
// Or, currying the first two arguments at once. | |
var curried6: (Int, Bool) -> (Character) -> String = curry2(function) | |
var curried7: ( Character) -> String = curried6(1, true) | |
var curried8: String = curried7 ("3") | |
var curried9: String = curried6(1, true)("3") | |
print("\(curried8) – currying, in two stages") | |
print("\(curried9) – currying, all at once") | |
} | |
func function(_ a1: Int, _ a2: Bool, _ a3: Character) -> String { | |
return "Result a1=\(a1) a2=\(a2) a3=\(a3)" | |
} | |
func applyPartial<T1, T2, T3, TResult>(_ f: @escaping (T1, T2, T3) -> TResult, p1: T1 ) -> (T2, T3) -> TResult { | |
return { (a2, a3) in f(p1, a2, a3) } | |
} | |
func applyPartial< T2, T3, TResult>(_ f: @escaping ( T2, T3) -> TResult, p2: T2 ) -> ( T3) -> TResult { | |
return { ( a3) in f( p2, a3) } | |
} | |
func applyPartial< T3, TResult>(_ f: @escaping ( T3) -> TResult, p3: T3 ) -> ( ) -> TResult { | |
return { ( ) in f( p3) } | |
} | |
func applyPartial<T1, T2, T3, TResult>(_ f: @escaping (T1, T2, T3) -> TResult, p1: T1, p2: T2) -> ( T3) -> TResult { | |
return { ( a3) in f(p1, p2, a3) } | |
} | |
func curry3<T1, T2, T3, TResult>(_ f: @escaping (T1, T2, T3) -> TResult) -> (T1) -> (T2) -> (T3) -> TResult { | |
return { a1 in { a2 in { a3 in f(a1, a2, a3) } } } | |
} | |
func curry2<T1, T2, T3, TResult>(_ f: @escaping (T1, T2, T3) -> TResult) -> (T1, T2) -> (T3) -> TResult { | |
return { (a1, a2) in { a3 in f(a1, a2, a3) } } | |
} | |
// Output: | |
// Result a1=1 a2=true a3=3 – normal call | |
// Result a1=1 a2=true a3=3 – partial application, binding a1 | |
// Result a1=1 a2=true a3=3 – partial application, binding a1,a2 | |
// Result a1=1 a2=true a3=3 – partial application, binding a1,a2,a3 | |
// Result a1=1 a2=true a3=3 – partial application, binding a1,a2 at once | |
// Result a1=1 a2=true a3=3 – partial application, binding a1,a2,a3 | |
// Result a1=1 a2=true a3=3 – currying, in three stages | |
// Result a1=1 a2=true a3=3 – currying, all at once | |
// Result a1=1 a2=true a3=3 – currying, in two stages | |
// Result a1=1 a2=true a3=3 – currying, all at once | |
} | |
PartialFunctionApplicationVsCurrying().main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment