Below a Compose function. If f and g are unary functions which return values, then Compose(f,g) returns a function which when called on x performs the equivalent to f(g(x)).
static Func<X, Z> Compose<Z, Y, X>(Func<Y, Z> f,Func<X, Y> g)
{ return x => f(g(x)); }
Here’s a couple of simple Func values which can be composed:
Func<int, bool> is_zero = x => { return x == 0; };
Func<int, int> mod_by_2 = x => { return x % 2; };
E.g. this works:
Console.WriteLine(Compose(is_zero, mod_by_2)(4));
However, if I instead have these equivalent static methods:
static bool IsZero(int n) { return n == 0; }
static int ModBy2(int n) { return n % 2; }
the same example doesn’t work with those. I.e. this produces a compile time error:
Console.WriteLine(Compose(IsZero, ModBy2)(4));
Explicitly passing types to Compose fixes the issue:
Console.WriteLine(Compose<bool, int, int>(IsZero, ModBy2)(4));
Is there anyway to write Compose such that it works on the static methods without the explicit types?
Is this a good approach to take to implementing Compose? Can anyone make improvements to this?
The problem here is not the use of
staticmethods but the use of method groups. When you use a function name as an expression without invoking it then it’s a method group and must go through method group conversion. You would have the exact same problem with instance methods.The problem you’re running into is that C# can’t do return type inference on method groups. Using
Compose(IsZero, ModBy2))requires the return type to be inferred for bothIsZeroandModBy2and hence this operation fails.This is a known limitation in the inference capabilities of the C# compiler. Eric Lippert wrote an extensive blog article on this particular subject which covers this problem in detail