2011-05-22 17 views
6

假设我想实现一个功能性成分,如:推断泛型类型与功能组合

public Func<T,T> Compose<T>(Func<T,T> f, Func<T,T> g) 
    { 
     return new Func<T,T>(x => f(g(x))); 
    } 

现在,在实践中,我可以用这个撰写()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); 

...但我得到一个编译错误:

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.

完全可以理解的。我想知道是否可以用不同的方式声明它,并推断实际的工作。


编辑
问题的由来:我在看一个本科生函数式编程过程中,加州大学伯克利分校的CS61A的在线讲座。 (在YouTube上找到它)。我没有任何关于FP的正式培训,我想我可能会学到一些东西。教授使用方案,他谈论了scheme + lisp是纯粹的函数式语言,而其他语言则不如此。他特别将Pascal,C,C++和Java(但不是C#)确定为缺乏功能性能力,并表示用这些语言进行功能组合很困难(“不要站在你的头上”)。他断言指向函数的指针(如C,C++中提供的)与lambda函数“entity”不同。我明白了。

有趣 - 他没有提到JavaScript或C#,我认为它们都是主流语言,它们都有很好的功能。 (我不知道F#)

我觉得很奇怪,这是去年 - 14个月前的演讲 - 但他似乎并不知道主流,现代语言的功能方面。

所以我正在跟着做练习,但不是使用scheme或lisp,而是使用C#。并在Javascript中使用其中的一些。

无论如何感谢大家对质量的回应。

+2

切线提示:您可以进一步这样概括你的'Compose'方法:http://paste.pocoo.org/show/393393/ – missingfaktor 2011-05-22 21:56:12

+2

功能组合是否有更通用的类型? (从Haskell(。)::(b→c) - >(a→b)→a→c)翻译出来的函数。 – 2011-05-23 01:26:18

回答

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); 

因此,也许你仍然可以得到你所定义只有一次的变量求可读性改善和他们重用他们在整个测试中(我假设这是一个测试实用程序...)

+0

这不是一个具体的测试实用程序,我只是“变得功能”,是一切。我使用过这种类型的测试线束,但这是独立的。 – Cheeso 2011-05-22 23:58:06

2

您也可以通过Compose参数,并且它具有评估的功能;它应该能够推断出这种情况下的参数类型。 (尽管如此,您可能仍然需要指定返回类型。)

除此之外,不,在C#中无法推断出这样的情况。

4

我喜欢Ran的答案(+1),但我认为这使它更加简洁和美观。(你必须重新定义功能如下可能性的假设下工作。)

Func<string, string> toUpper = s => s.ToUpper(); 
Func<string, string> replicate = s => s + s; 

var h = Compose(toUpper, replicate); 
4

添加到lasseespeholt的答案,如果你定义撰写作为一个扩展方法(更名为“然后”,使结果更有意义):

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... 
+0

不错........... – Cheeso 2011-05-22 23:48:36