I've been looking into Functional Programming lately and wanting to bring some concepts to my C#
world. I'm trying to compose functions to create services (or whatever you'd call them) instead of creating classes with injectable dependencies.
I've come up with a way to partially apply a function (to have the same effect as injecting dependencties) with two arguments and one return argument by creating a static method like this:
// this makes a func with a single arg from a func with two
static Func<T2, TResult> PartiallyApply<T1, T2, TResult>(
Func<T1,T2, TResult> f,
T1 t1)
{
// use given t1 argument to create a new function
Func<T2, TResult> map = t2 => f(t1, t2);
return map;
}
This works, however I would like to pass it a static method, like this one:
static string MakeName(string a, string b) => a + " " + b;
When I try to wire this up, I get the error The type arguments for method 'Program.PartiallyApply<T1, T2, TResult>(Func<T1, T2, TResult>, T1)' cannot be inferred from the usage.
But when I add a step creating an explicit Func<string,string,string
which I point to the method it does work:
static void Main(string[] args)
{
var first = "John";
var last = "Doe";
var f1 = PartiallyApply(MakeName, first); // cannot be inferred from the usage
Func<string, string, string> make = MakeName; // map it to func
var f2 = PartiallyApply(make, first); // works
var name = f2(last);
Console.WriteLine(name);
Console.ReadKey();
}
Why can't the compiler work out the type args when passing the static method directly? Is there a way where I could use static methods without the need to explicitly map them to a Func<>
with essentially the same (type) arguments?
UPDATE
Reading Functional programming in C#
by Enrico Buonanno
(highly recommended) gives another good option for getting around this. In 7.1.3
he gives several options on how to work with Funcs
directly, instead of method groups.
You could make a getter only property with a Func
like this:
static Func<string, string, string> MakeName => (a,b) => a + " " + b;
MakeName
itself (assuming it is yours to maintain):static Func<string, Func<string, string> MakeName = a => b => a + " " + b;
Recommended reading: codeblog.jonskeet.uk/2012/01/30/… – Pavement