我是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期待一个元组。
是否有某种形式的语法允许我完成此操作,或者如果我想使用函数组合,我是否必须始终执行某种中间函数来转换值?
对此的任何建议都将非常感激。
答案 0 :(得分:8)
正如Yin和codekaizen指出的那样,你不能组合这两个函数来创建一个函数,将输入传递给第一个函数,然后将这个调用的输出传递给第二个函数(即,使用th {{1}运营商)。使用图表,你不能这样做:
>>
一个选项是更改功能并指定其中一个参数,以便可以组合功能。 codekaizen的例子使用了这个,也可以像这样编写(如果你使用currying而不是tupled参数):
+---------+ +---------+
--->| AddNums |--->| MulNums |--->
+---------+ +---------+
组合函数的另一个选项是创建一个函数,它接受几个输入,将两个数字传递给第一个函数,然后用结果调用第二个函数,从原始输入调用另一个数字。使用图表:
let AddNums x y = x + y
let MulNums x y = x * y
let FuncComp = (AddNums 1) >> (MulNums 2)
如果你需要这样的东西,那么最好的选择是直接写,因为这可能不是一个经常重复的模式。直接地,这很容易(使用curried变体):
-----------------\
--->+---------+ \+---------+
--->| AddNums |--->| MulNums |--->
+---------+ +---------+
如果你想更一般地写一些这样的东西(或仅仅是为了好奇心),你可以写这样的东西(这次使用函数的三元组版本)。 let AddNums x y = x + y
let MulNums x y = x * y
let FuncComp x y z = AddNums z y |> (MulNums z)
运算符的灵感来自Arrows:
&&&
答案 1 :(得分:1)
正如Yin指出的那样,你的作品在作曲时并不匹配。 AddNums
和MulNums
的类型为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 it:int = 4
答案 2 :(得分:1)
另一种选择是使stack->堆栈函数与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)