Last active
September 15, 2016 11:51
-
-
Save philiplaureano/51413336b6c3c6d604e3 to your computer and use it in GitHub Desktop.
Currying and chaining funcs and actions together in C#
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
public static class FunctionalBindingExtensions | |
{ | |
public static Action<T2> Bind<T1, T2>(this Action<T1, T2> action, Func<T1> getValueFunc) | |
{ | |
return action.Bind(getValueFunc()); | |
} | |
public static Action<T1> Bind<T1, T2>(this Action<T1, T2> action, Func<T2> getValueFunc) | |
{ | |
return action.Bind(getValueFunc()); | |
} | |
public static Action<T2> Bind<T1, T2>(this Action<T1, T2> action, T1 value) | |
{ | |
return openArg => action(value, openArg); | |
} | |
public static Action<T1> Bind<T1, T2>(this Action<T1, T2> action, T2 value) | |
{ | |
return openArg => action(openArg, value); | |
} | |
public static Action Bind<T1>(this Action<T1> action, Func<T1> getValueFunc) | |
{ | |
return () => action(getValueFunc()); | |
} | |
public static Action Bind<T1>(this Action<T1> action, T1 value) | |
{ | |
return () => action(value); | |
} | |
public static Func<T1, TResult> BindFirst<T1, TResult>(this Func<T1, T1, TResult> func, Func<T1> getValueFunc) | |
{ | |
return openArg => func(getValueFunc(), openArg); | |
} | |
public static Func<T1, TResult> BindFirst<T1, TResult>(this Func<T1, T1, TResult> func, T1 value) | |
{ | |
return openArg => func(value, openArg); | |
} | |
public static Func<T1, TResult> BindSecond<T1, TResult>(this Func<T1, T1, TResult> func, Func<T1> getValueFunc) | |
{ | |
return openArg => func(openArg, getValueFunc()); | |
} | |
public static Func<T1, TResult> BindSecond<T1, TResult>(this Func<T1, T1, TResult> func, T1 value) | |
{ | |
return openArg => func(openArg, value); | |
} | |
public static Func<T2, TResult> Bind<T1, T2, TResult>(this Func<T1, T2, TResult> func, Func<T1> getValueFunc) | |
{ | |
return func.Bind(getValueFunc()); | |
} | |
public static Func<T2, TResult> Bind<T1, T2, TResult>(this Func<T1, T2, TResult> func, T1 value) | |
{ | |
return openArg => func(value, openArg); | |
} | |
public static Func<T1, TResult> Bind<T1, T2, TResult>(this Func<T1, T2, TResult> func, Func<T2> getValueFunc) | |
{ | |
return func.Bind(getValueFunc()); | |
} | |
public static Func<T1, TResult> Bind<T1, T2, TResult>(this Func<T1, T2, TResult> func, T2 value) | |
{ | |
return openArg => func(openArg, value); | |
} | |
public static Func<TResult> Bind<T1, TResult>(this Func<T1, TResult> func, Func<T1> getValueFunc) | |
{ | |
return func.Bind(getValueFunc()); | |
} | |
public static Func<TResult> Bind<T1, TResult>(this Func<T1, TResult> func, T1 value) | |
{ | |
return () => func(value); | |
} | |
} | |
public static class FunctionalExtensions | |
{ | |
public static Func<T2> Combine<T1, T2>(this Func<T1> firstFunc, Func<T1, T2> secondFunc) | |
{ | |
return () => secondFunc(firstFunc()); | |
} | |
public static Func<T1, T3> Combine<T1, T2, T3>(this Func<T1, T2> firstFunc, Func<T2, T3> secondFunc) | |
{ | |
return firstArg => secondFunc(firstFunc(firstArg)); | |
} | |
public static Action<T1> Combine<T1>(this Action<T1> firstAction, Action<T1> secondAction) | |
{ | |
return arg => | |
{ | |
firstAction(arg); | |
secondAction(arg); | |
}; | |
} | |
public static Action Combine(this Action firstAction, Action secondAction) | |
{ | |
return () => | |
{ | |
firstAction(); | |
secondAction(); | |
}; | |
} | |
public static Action<T2, T3> Do<T1, T2, T3>(this Func<T1> func, Func<T1, Action<T2, T3>> createAction) | |
{ | |
return createAction(func()); | |
} | |
public static Func<T1> Do<T1>(this Func<T1> func, Action<T1> applyAction) | |
{ | |
return () => | |
{ | |
var result = func(); | |
applyAction(result); | |
return result; | |
}; | |
} | |
public static Func<T2> Return<T1, T2>(this Func<T1> func, Func<T1, T2> transformFunc) | |
{ | |
return () => transformFunc(func()); | |
} | |
} | |
public static class Instance | |
{ | |
public static Func<T> Of<T>() | |
where T : new() | |
{ | |
return () => new T(); | |
} | |
public static Func<T1> Of<T1>(this T1 instance) | |
{ | |
return () => instance; | |
} | |
} | |
// Here's how you use it: | |
public class Person | |
{ | |
public int Age { get; set; } | |
public string Name { get; set; } | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
// Currying example - first declare the original Func | |
Func<int, int, int> add = (a, b) => a + b; | |
// Convert the func into a Func<int, int> and bind '2' to the first parameter | |
var addTwo = add.BindFirst(2); | |
var alwaysReturnFour = addTwo.Bind(2); | |
// This will print "4" | |
Console.WriteLine(alwaysReturnFour()); | |
var person = new Person {Age = 18, Name = "John Smith"}; | |
// Create the chain of actions to execute against the target person object | |
var printNameAndAge = Instance.Of(person) | |
.Do(p => Console.WriteLine("My name is {0}", p.Name)) | |
.Do(p=>Console.WriteLine("My age is: {0}", p.Age)); | |
printNameAndAge(); | |
Console.WriteLine("Press any key to continue..."); | |
Console.ReadKey(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment