如何使用管道运算符重写此函数

时间:2013-05-31 07:40:32

标签: f#

这些是函数定义。

func1: 'a -> unit
func2: 'b -> 'a
func3: string -> 'b list    

当前功能

let f =  Seq.iter((fun a -> func1(func2 a)) func3(s) 

就我而言

let f =  func3(s) 
           |> ((fun a -> func2 a 
                         |> func1) 
           |> Seq.iter)

我觉得应该可以松开lambda和parens'。

3 个答案:

答案 0 :(得分:6)

你可以不用管道,只需

Seq.iter (func1 << func2) << func3

(这是一个带有一些参数的函数[与func3相同],输出与Seq.iter相同)。

你可以测试它

let func1 x = printfn "Number: %d" x

let func2 (a, b) = a + b

let func3 = Seq.map (fun n -> (n, 2 * n))

let f : (seq<_> -> unit) = Seq.iter (func1 << func2) << func3

f [1..5]

带输出

Number: 3
Number: 6
Number: 9
Number: 12
Number: 15

val func1 : x:int -> unit
val func2 : a:int * b:int -> int
val func3 : (seq<int> -> seq<int * int>)
val f : (seq<int> -> unit)
val it : unit = ()

:)

答案 1 :(得分:4)

您可以使用函数组合运算符>>

func3() |> Seq.iter (func2 >> func1)

答案 2 :(得分:2)

我认为问题是,为什么要使用管道运算符?

我发现您的原始代码非常易读。您不应该仅仅为了使用它们而尝试使用管道操作符(或函数组合)。现在,在您的代码中,输入s出现在最后,这有点不幸(您无法完全看到代码的主要输入)。我可能会把它重写为(同样,s并不是一个真正的描述性名称):

s |> func3 
  |> Seq.iter (fun a -> func1 (func2 a))

你也可以使用功能组合 - 但我不经常使用它,因为它不会(总是)帮助提高可读性。但是在Seq.iter的论证中使用它可能是非常合理的。

在完全不相关的说明中,您可以使用for循环并写入:

for a in func3 s do
  func1 (func2 a)

我实际上发现这比任何其他版本的代码更具可读性(如果F#为您提供了一种语言功能,可以迭代完全符合您需要的序列,为什么不使用它?)