Skip to content

Instantly share code, notes, and snippets.

@philiplaureano
Last active September 15, 2016 11:51
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save philiplaureano/51413336b6c3c6d604e3 to your computer and use it in GitHub Desktop.
Save philiplaureano/51413336b6c3c6d604e3 to your computer and use it in GitHub Desktop.
Currying and chaining funcs and actions together in C#
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