2014-09-05 41 views
1

假設我們有許多過濾函數接受相同的參數並返回布爾結果。將函數與相同但部分未知的簽名組合使用

let filter1 _ _ = true 
let filter2 _ _ = false 

這些可以組合成一個過濾器。

let combine2 f1 f2 = fun a b -> f1 a b && f2 a b 
combine2 filter1 filter2 

我們實現需要的f1f2參數的一些知識。更一般地,我們可以找到功能combine1 ... combineN有用,其中N是過濾器功能的參數數量。可以編寫一個與N無關的通用combine函數嗎?

我對F#的功能感興趣,並且能夠在其他情況下應用此概念。

更新:我對問題的理解是,當他們不關心結果是簡單類型還是部分應用函數時,函數會成功忽略任何其餘參數。在上面的例子中,我們只在應用所有參數後才達到布爾類型,所以需要指定它們。

+1

我有理由相信,這樣一個通用的結合不能寫,同時確保類型安全 – 2014-09-05 02:11:29

+0

好吧,有'printf'功能,它使用一點魔法來做事情。 [This](http://stackoverflow.com/a/5572812/612512)可能會有用。 – 2014-09-05 05:08:46

+0

@christopher從我讀過的([這裏](http://bugsquash.blogspot.com.au/2010/07/abusing-printfformat-in-f.html)),'printf'的實現是由編譯器而不是僅僅使用f#和.net結構。您提供的鏈接建立在此功能之上,我不瞭解如何在這種情況下應用它。 – cadull 2014-09-12 05:10:52

回答

2

使用高階函數,傳遞函數作爲參數

let combineN invoke filters = filters |> List.map invoke |> List.reduce (&&) 

,並使用它像這樣

[filter1; filter2] |> combineN (fun f -> f 1 2) |> printfn "%b" 

演示:https://dotnetfiddle.net/EHC5di

你也可以通過List.reduce參數作爲參數,如combineN (&&) (fun f -> f 1 2) 但通常更容易編寫List.map |> List.reduce

你也可以用多個參數用它

let filter3 _ _ _ = true 
let filter4 _ _ _ = true 

[filter3; filter4] |> List.map (fun f -> f 1 2 3) |> List.reduce (&&) |> printfn "%b" 
[filter3; filter4] |> combineN (fun f -> f 1 2 3) |> printfn "%b" 

編譯器會檢查類型(編號參數)

//call list of function with 2 argument, with more arguments doesnt compile 
[filter1; filter2] |> combineN (fun f -> f 1 2 3) |> printfn "%b" 
//mix functions with different arguments, doesnt compile either 
[filter1; filter3] |> combineN (fun f -> f 1 2 3) |> printfn "%b" 

看到演示

+1

我認爲這個想法是有N個參數,而不是N個函數 – 2014-09-05 09:51:57

+1

使用可以使用更多的參數''[filter3; filter4] |> combineN(fun f - > f 1 2 3)''。是類型檢查,請參閱演示 – 2014-09-05 09:54:03

+0

我喜歡這個答案,因爲它自然擴展了這個例子來組合兩個以上的過濾器。仍然依賴'N'來實現組合過濾器函數'fun a b - > [filter1; filter2] |> combineN(fun f - > f a b)',但是在合併過程中的任何複雜性都是抽象的。正如@john所說的那樣,用這種設計對'N'的依賴可能是不可避免的。 – cadull 2014-09-09 04:12:34

相關問題