通过函数组合推断泛型类型
假设我想实现一个函数组合,如下所示:
public Func<T,T> Compose<T>(Func<T,T> f, Func<T,T> g)
{
return new Func<T,T>( x => f(g(x)));
}
现在在实践中,我可以像这样使用此 Compose() fn:
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"));
}
结果是 FREDFRED
。
有没有办法使用更简单的语法来调用 Compose?我尝试这样:
var h = Compose(ToUpper, Replicate);
...但我收到编译错误:
错误CS0411:无法从用法中推断出方法“FunctionalTest.Compose(System.Func, System.Func)”的类型参数。尝试显式指定类型参数。
很好理解。我想知道是否可以以不同的方式声明它并使推论真正起作用。
编辑
问题的根源:我正在观看本科生函数式编程课程的在线讲座,加州大学伯克利分校的CS61A。 (在 youtube 上找到它)。我没有接受过任何关于 FP 的正式培训,我想我可能会学到一些东西。教授使用了scheme,他谈到scheme + lisp是纯粹的函数式语言,而其他语言则不然。他特别指出 Pascal、C、C++ 和 Java(但不是 C#)缺乏函数式能力,并表示用这些语言进行函数式组合会很困难(“如果不倒立”)。他断言函数指针(在 C、C++ 中可用)与函数“实体”(即 lambda)不同。我明白了。
有趣的是 - 他没有提到 Javascript 或 C#,我认为它们是主流语言,两者都具有相当好的功能。 (我不认识 F#。)
我觉得奇怪的是,这是去年(14 个月前)的讲座,但他似乎不了解主流现代语言的功能方面。
所以我正在跟着做练习,但我没有使用 schema 或 lisp,而是使用 C#。并且还用 Javascript 完成了其中的一些工作。
无论如何,感谢大家的高质量回复。
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 languages, 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您也可以传递
Compose
参数,并让它实际评估函数;在这种情况下它应该能够推断出参数类型。 (不过,您可能仍然需要指定返回类型。)除此之外,不,没有办法在 C# 中推断出这样的事情。
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#.
添加到 lasseespeholt 的答案中,如果您将 Compose 定义为扩展方法(重命名为“Then”,以便结果更有意义):
您可以使其变得流畅:
Adding to lasseespeholt's answer, if you define Compose as an extension method (renamed "Then" so that the result makes more sense):
you can make this fluent:
以下代码可以工作:
因此,也许您仍然可以通过仅定义这些变量一次并在整个测试中重用它们来获得您正在寻求的可读性改进(我假设这是一个测试实用程序...)
The following code would work:
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...)
我喜欢 Ran 的回答(+1),但我认为这使它更加简洁和漂亮。 (假设您可以按如下方式重新定义函数。)
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.)