2011-05-22 51 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