2010-07-10 76 views
5

我新的F#和最近我發現功能複合算>>F#功能組成參數

我理解的基本原則,使這樣的事情是可能的....

let Add1ToNum x = x +1 
let Mul2ToNum y = y * 2 
let FuncComp = Add1ToNum >> Mul2ToNum 

然而,如何將一個處理當你有有不同數量的輸入參數的幾個函數組成......比如我想能夠做到以下...

let AddNums (x,y) = x+y 
let MulNums (x,y) = x*y 
let FuncComp = Add1 >> Mul2 

這顯然不起作用,因爲AddNums返回一個int,而MulNums期待一個元組。

是否有某種形式的語法允許我完成此操作,或者如果我想要使用函數組合,是否必須始終執行某種中介函數來轉換值?

任何建議,將不勝感激。

+4

我不太看你使用'AddNum >> MulNums',點AddNums的輸出爲單數,因此不MulNums的有效輸入格式,這意味着兩個功能根本不復合。 – 2010-07-10 07:19:47

回答

8

作爲陰和codekaizen指出,不能構成兩個函數以創建將輸入到第一個函數,並且然後這個調用的輸出傳遞到第二個函數(即使用運算符>>)。使用圖表,你不能做:

 +---------+ +---------+ 
--->| AddNums |--->| MulNums |---> 
    +---------+ +---------+ 

一個選項是改變功能,並指定其中的一個參數,這樣的功能可以組成。通過codekaizen本例使用這一點,可也這樣寫的(如果你使用的討好,而不是tupled參數):

let AddNums x y = x + y 
let MulNums x y = x * y 
let FuncComp = (AddNums 1) >> (MulNums 2) 

了構成功能的另一種選擇是創建一個函數,它有多個輸入,通過兩個數字到第一個函數,然後用原始輸入的結果和另一個數字調用第二個函數。使用圖:

-----------------\ 
--->+---------+ \+---------+ 
--->| AddNums |--->| MulNums |---> 
    +---------+ +---------+ 

如果你需要類似的東西,那麼最好的選擇是直接寫,因爲這可能不會是一個經常重複的模式。直接,這是容易的(使用咖喱變體):

let AddNums x y = x + y 
let MulNums x y = x * y 
let FuncComp x y z = AddNums z y |> (MulNums z) 

如果你想寫類似的東西更普遍(或只是出於好奇),你可以寫這樣的事情(使用的功能,這個tupled版本時間)。該&&&操作由Arrows啓發:

let AddNums (x,y) = x + y 
let MulNums (x,y) = x * y 

let (&&&) f g (a, b) = (f a, g b) 
let FuncComp = (AddNums &&& id) >> MulNums 

// First two numbers are added, result is multiplied by the third one 
FuncComp ((9, 12), 2) // Gives '42' 
+0

謝謝托馬斯,這個解釋得非常好! – 2010-07-10 12:54:58

+0

@Tomas:我擔心你從箭頭中使用了錯誤的操作符。應該是(***);) – Gustavo 2011-12-05 18:23:46

+0

let(***)f g(a,b)=(f a,g b) let(&&&)f g a =(f a,g a) – ben 2014-06-17 16:01:38

1

正如Yin指出的,你的類型在編寫時不匹配。 AddNumsMulNums的類型爲int * int -> int,因此您不能指望將一個輸出插入另一個的輸入。

我注意到,你的最後一行是let FuncComp = Add1 >> Mul2這可能是一個錯字,但給出的洞察力如何可以「綁定」內搭元組的功能,使它們組成:

let Add1 x = AddNums(x, 1) 
let Mul2 x = MulNums(x, 2) 
let FuncComp = Add1 >> Mul2 

當運行:

FuncComp(1);;

VAL它:整數= 4

+0

感謝codekaizen,我在我的問題中指出,我意識到一個函數的輸出與另一個函數的輸入不同,並且函數組合運算符不起作用,但正在尋找可能的替代解釋。 – 2010-07-10 12:54:41

1

另一個選擇是讓重新建立了新>堆棧功能很像一個RPN計算器。例如:

let bin f = function a :: b :: t -> f b a :: t 
let add = bin (+) 
let mul = bin (*) 

也許功能推文字堆棧:

let lit n t = n :: t 

然後,它的純的組合:

> (lit 9 >> lit 12 >> add >> lit 2 >> mul) [] 
42 

你甚至可以添加堆棧洗牌功能:

let drop = function _ :: t -> t 
let dup = function x :: t -> x :: x :: t 
let swap = function x :: y :: t -> y :: x :: t 

然後執行如下操作:

let square = dup >> mul 
let cube = dup >> dup >> mul >> mul 
let negate = lit -1 >> mul 

只是一個瘋狂的實驗!

(也http://blogs.msdn.com/b/ashleyf/archive/2011/04/21/programming-is-pointless.aspx見)