2010-07-10 83 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见)