I tried experimenting with the new C#14 extension syntax. As an example, I wanted to implement a simulation of function currying using the << operator.
public static class Curry
{
extension<T1, T2, T3>(Func<T1, T2, T3>)
{
public static Func<T2, T3> operator <<(Func<T1, T2, T3> f, T1 param)
=> t2 => f(param, t2);
}
}
This works for explicitly delegate types:
static void Test()
{
Func<int, int> curr = (Func<int, int, int>)((a, b) => a + b) << 10;
int result = curr(10); // result = 10 + 10 = 20
}
However, as you might imagine, this will not work with lambda expressions or method group types:
static int Add(int a, int b) => a + b;
static void Test()
{
Func<int, int> curr = Add << 10; // Operator '<<' cannot be applied to operands of type 'method group' and 'int'
}
My question is the following: is it then possible to make this work seamlessly with methods and lambdas without having to rely on explicit casts to a delegate type?
Func<int, int, int>as in your first case. Second, even in F# – which supports currying – you would need to show the arguments are passed to the call toAddand then the result is then passed to the shift operator.double Add(double, double)method? What would the type argument be? I guess it would be possible to infer in some cases, but it is probably quite a bit of work for the compiler writers to handle a specific edge case. And you can workaround the issue easily enough by just casting the method group to the delegate type.var interimVar = Add; Func<int, int> curr = interimVar << 10(leveraging the natural function type feature added in previous versions)public static Func<T2, T3> operator >>(T1 param, Func<T1, T2, T3> f) => t2 => f(param, t2);and thenFunc<int, int> curr = 10 >> Add;extension<T1, T2, T3>(Func<T1, T2, T3> f) { public Func<T2, T3> curry( T1 param)=> t2 => f(param, t2); }. This will work with both delegates and lambdas, once you get the parentheses right.