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;
Because if you has two methods with different arguments compiler don't know use method1 or method2.
example:
static string MakeName(string a, string b) => a + " " + b;
static string MakeName(int a, string b) => a + " " + b;
How could the compiler know which one you mean? Method1 or method2? Just because you only have one method in the method group now, doesn't mean it will always be that way. Adding a method would then break in this manner.
var f1 = PartiallyApply(MakeName, first);
So if you want to fix this problem you have to set your generic arguments in the method calling:
var f1 = PartiallyApply<string, string, string>(MakeName, first);
var f2 = PartiallyApply<string, int, string>(MakeName, first);
Or you can get all of arguments in your PartiallyApply method:
static string MakeName(string a, string b) => a + " " + b;
static string MakeName(int a, string b) => a + " " + b;
// 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,
T2 t2)
{
// use given t1 argument to create a new function
Func<T2, TResult> map = result => f(t1, t2);
return map;
}
static void Main(string[] args)
{
var first = "John";
var last = "Doe";
var f1 = PartiallyApply(MakeName, first, last); //works now
var name = f1(last);
Console.WriteLine(name);
Func<string, string, string> make = MakeName; // map it to func
var f2 = PartiallyApply(make, first, last); // works
name = f2(last);
Console.WriteLine(name);
Console.ReadKey();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With