Last active
March 17, 2020 23:41
-
-
Save daveyostcom/307aedf294042d0aba596cda9cc480ea to your computer and use it in GitHub Desktop.
partial function application vs currying – exploded view
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
using System; | |
namespace PartialFunctionApplicationVsCurrying { | |
// Consider this heavily-aligned source code as a kind of exploded view to aid understanding. | |
// Func<> documentation https://docs.microsoft.com/en-us/dotnet/api/system.func-4 | |
// 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 { | |
// This ordinary function is our starting point. | |
static string SampleFunction(int a1, bool a2, char a3) | |
=> string.Format("Result a1={0} a2={1} a3={2}", a1, a2, a3); | |
internal static void Main(string[] args) { | |
// Call the function directly. No tricks. ----- print this ----- | |
Func<int, bool, char, string> function = SampleFunction; | |
Console.WriteLine("{0} – normal call", function(1, true, '3')); | |
// Call via partial application, binding one arg at a time. | |
Func< bool, char, string> partial1 = ApplyPartial1__(function, 1); | |
Func< char, string> partial2 = ApplyPartial12_(partial1, true); | |
Func< string> partial3 = ApplyPartial123(partial2, '3'); | |
Console.WriteLine("{0} – partial application, binding a1", partial1( true, '3')); | |
Console.WriteLine("{0} – partial application, binding a1,a2", partial2( '3')); | |
Console.WriteLine("{0} – partial application, binding a1,a2,a3", partial3( )); | |
// Call via partial application, binding a1,a2 then a3. | |
Func< char, string> partial4 = ApplyPartial12(function, 1, true); | |
Func< string> partial5 = ApplyPartial123(partial4, '3'); | |
Console.WriteLine("{0} – partial application, binding a1,a2 at once", partial4( '3')); | |
Console.WriteLine("{0} – partial application, binding a1,a2,a3", partial5( )); | |
// Call via currying, one arg at a time. | |
Func<int, Func<bool, Func<char, string>>> curried1 = Curry3(function); | |
Func<bool, Func<char, string>> curried2 = curried1(1) ; | |
Func<char, string> curried3 = curried2 (true) ; | |
string curried4 = curried3 ('3'); | |
Console.WriteLine("{0} – currying, stage 1", curried1(1)(true)('3')); | |
Console.WriteLine("{0} – currying, stage 2", curried2 (true)('3')); | |
Console.WriteLine("{0} – currying, stage 3", curried3 ('3')); | |
Console.WriteLine("{0} – currying, complete", curried4); | |
// Call all stages at once. | |
string curried5 = curried1(1)(true)('3'); | |
Console.WriteLine("{0} – currying, all at once", curried5); | |
// Or, currying the first two arguments together. | |
Func<int, bool, Func<char, string>> curried6 = Curry2(function); | |
Func<char, string> curried7 = curried6(1, true); | |
string curried8 = curried7 ('3'); | |
Console.WriteLine("{0} – currying, in two stages", curried8); | |
// Call all stages at once. | |
string curried9 = curried6(1, true)('3'); | |
Console.WriteLine("{0} – currying, all at once", curried9); | |
} | |
// Partial application | |
static Func< T2, T3, TResult> // return type | |
ApplyPartial1__<T1, T2, T3, TResult> // invocation name & types | |
(Func<T1, T2, T3, TResult> f, T1 a1) // arguments | |
=> ( p2, p3) // resulting | |
=> f(a1, p2, p3); // function | |
static Func< T3, TResult> | |
ApplyPartial12_< T2, T3, TResult> | |
(Func< T2, T3, TResult> f, T2 a1) | |
=> ( p2 ) | |
=> f(a1, p2 ); | |
static Func< TResult> | |
ApplyPartial123< T3, TResult> | |
(Func< T3, TResult> f, T3 a1) | |
=> ( ) | |
=> f(a1 ); | |
// Or, binding the first two arguments at once. | |
static Func< T3, TResult> | |
ApplyPartial12 <T1, T2, T3, TResult> | |
(Func<T1, T2, T3, TResult> f, T1 a1, T2 a2) | |
=> ( p3) | |
=> f(a1, a2, p3); | |
// Currying | |
static Func<T1, Func<T2, Func<T3, TResult>>> | |
Curry3 <T1, T2, T3, TResult> | |
(Func<T1, T2, T3, TResult> f) | |
=> a1 => a2 => a3 | |
=> f(a1, a2, a3); | |
static Func<T1, T2, Func<T3, TResult>> | |
Curry2 <T1, T2, T3, TResult> | |
(Func<T1, T2, T3, TResult> f) | |
=> (a1, a2) => a3 | |
=> 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, stage 1 | |
// Result a1=1 a2=True a3=3 – currying, stage 2 | |
// Result a1=1 a2=True a3=3 – currying, stage 3 | |
// Result a1=1 a2=True a3=3 – currying, complete | |
// 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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment