Inferring generic types with functional composition
Suppose I want to implement a functional composition, like this:
public Func<T,T> Compose<T>(Func<T,T> f, Func<T,T> g)
{
return new Func<T,T>( x => f(g(x)));
}
Now in practice, I can use this Compose() fn like this:
public String ToUpper(String s) { return s.ToUpper(); }
public String Replicate(String s) { return s+s; }
public void Run()
{
var h = Compose<String>(ToUpper, Replicate);
System.Console.WriteLine("{0}", h("fred"));
}
And the result is FREDFRED
.
Is there a way to use a simpler syntax to invoke Compose? I tried like this:
var h = Compose(ToUpper, Replicate);
...but I get a compile error:
error CS0411: The type arguments for method 'FunctionalTest.Compose(System.Func, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Quite understandable. I am wondering if it is possible to declare it differently and get the inference to actually work.
EDIT
The origin of the problem: I was watching an online lecture of an undergrad Functional Programming course, UC Berkley's CS61A. (find it on youtube). I don't have any formal training on FP, and I thought I might learn something. The prof uses scheme and he talks about how scheme + lisp are purely functional lan开发者_运维百科guages, and other languages are less so. He specifically identified Pascal, C, C++, and Java (but not C#) as lacking functional capabilities, and said it would be difficult to do functional composition with these languages ("Without standing on your head"). He asserted that a pointer-to-function (as available in C, C++) is not the same as a function "entity", a lambda. I get that.Funny - he didn't mention Javascript or C#, which I consider to be mainstream languages that both have pretty good functional capabilities. (I don't know F#.)
I find it curious that this is a lecture from last year - 14 months ago - and yet he seems to be unaware of the functional aspects of mainstream, modern languages.
So I'm following along and doing exercises, but instead of using scheme or lisp, I'm using C#. And also doing some of them in Javascript.
Anyway thanks to everyone for the quality responses.
Adding to lasseespeholt's answer, if you define Compose as an extension method (renamed "Then" so that the result makes more sense):
public static Func<T, T> Then<T>(this Func<T, T> f, Func<T, T> g)
{
return x => g(f(x));
}
you can make this fluent:
var h = toUpper.Then(replicate); // .Then(trim) etc...
The following code would work:
Func<string, string> toUpper = ToUpper;
Func<string, string> replicate = Replicate;
// now the compiler knows that the parameters are Func<string, string>
var h = Compose(toUpper, replicate);
So maybe you can still get the readability improvement you are seeking by defining those variables only once and them reusing them throughout your tests (I'm assuming this is a test utility...)
I like Ran´s answer (+1), but I think this make it a little more concise and nice. (Works under the assumption that you have the possibility to redefine the functions as follows.)
Func<string, string> toUpper = s => s.ToUpper();
Func<string, string> replicate = s => s + s;
var h = Compose(toUpper, replicate);
You could pass Compose
the parameter too, and have it actually evaluate the function; it should be able to infer the parameter type in that case. (You might need to still specify the return type, though.)
Other than that, no, there's no way to infer things like this in C#.
精彩评论