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?
In mathematics, function composition is an operation ∘ that takes two functions f and g, and produces a function h = g ∘ f such that h(x) = g(f(x)). In this operation, the function g is applied to the result of applying the function f to x.
A composite function is generally a function that is written inside another function. Composition of a function is done by substituting one function into another function. For example, f [g (x)] is the composite function of f (x) and g (x). The composite function f [g (x)] is read as “f of g of x”.
The problem here is not the use of static
methods 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 both IsZero
and ModBy2
and 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
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