我了解F#中函数组合的基础知识,例如here所述。
不过,也许我缺少了一些东西。 >>
和<<
运算符似乎是在假设每个函数仅接受一个参数的前提下定义的:
> (>>);;
val it : (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) = <fun:it@214-13>
> (<<);;
val it : (('a -> 'b) -> ('c -> 'a) -> 'c -> 'b) = <fun:it@215-14>
但是,我想做的事情如下:
let add a b = a + b
let double c = 2*c
let addAndDouble = add >> double // bad!
但是,即使
add
的输出是double
的输入所需的类型,也将被拒绝。我知道我可以用一个元组参数重写add:
let add (a,b) = a + b
或者,我可以为第一个函数的所有可能参数编写一个新的运算符:
let inline (>>+) f g x y = g (f x y)
let doubleAdd = add >>+ double
但这似乎很愚蠢!我错过了更好的方法吗?
最佳答案
您想要的不是完全没有道理的,但是没有办法在F#的类型系统中指示广义组合运算符的类型。也就是说,没有统一的好方法
(>>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c
和
(>>+) : ('a -> 'b -> 'c) -> ('c -> 'd) -> 'a -> 'b -> 'd
(更不用说无限多个高级Arity版本了)。因此,您别无选择,只能定义自己的其他运算符。实际上,我经常发现以“指向”样式
let f x y = add x y |> double
编写的代码比无点/“无指向” let f = add (>>+) double
更具可读性。
关于f# - 我缺少什么: is function composition with multiple arguments possible?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5446199/