假设我想实现一个功能组合,如下所示:
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)'的类型参数。尝试明确指定类型参数。
完全可以理解。我想知道是否有可能以不同方式声明它并得到推断实际工作。
修改
问题的根源:我正在观看本科生功能编程课程的在线讲座,UC Berkley的CS61A。 (在youtube上找到它)。我没有关于FP的正式培训,我想我可能会学到一些东西。教授使用方案,他谈到方案+ lisp是纯函数式语言,而其他语言则不那么简单。他特别指出Pascal,C,C ++和Java(但不是C#)缺乏功能,并表示用这些语言进行功能组合很难(“没有站在你的头上”)。他声称指向函数的指针(在C,C ++中可用)与函数“entity”(lambda)不同。我明白了。
搞笑 - 他没有提到Javascript或C#,我认为它们是主流语言,它们都具有相当不错的功能。 (我不知道F#。)
我觉得很奇怪这是去年 - 14个月前的一次演讲 - 然而他似乎并没有意识到主流现代语言的功能方面。
所以我跟着做练习,但不是使用scheme或lisp,而是使用C#。并且还在Javascript中执行其中一些操作。
无论如何,感谢大家对质量的反应。
答案 0 :(得分:4)
以下代码可行:
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);
所以也许你仍然可以通过仅定义这些变量一次来获得你正在寻求的可读性改进,并且他们在整个测试中重复使用它们(我假设这是一个测试实用程序......)
答案 1 :(得分:4)
我喜欢Ran的回答(+1),但我认为这会让它更简洁,更好。 (假设您有可能重新定义函数,请按照以下方式工作。)
Func<string, string> toUpper = s => s.ToUpper();
Func<string, string> replicate = s => s + s;
var h = Compose(toUpper, replicate);
答案 2 :(得分:4)
添加到lasseespeholt的答案,如果您将Compose定义为扩展方法(重命名为“Then”以便结果更有意义):
public static Func<T, T> Then<T>(this Func<T, T> f, Func<T, T> g)
{
return x => g(f(x));
}
你可以说得这么流利:
var h = toUpper.Then(replicate); // .Then(trim) etc...
答案 3 :(得分:2)
您也可以传递Compose
参数,并让它实际上评估该函数;它应该能够推断出那种情况下的参数类型。 (但是,您可能仍需要指定返回类型。)
除此之外,不,没有办法在C#中推断出这样的事情。