如果管道运算符是这样创建的:
let (|>) f g = g f
并像这样使用:
let result = [2;4;6] |> List.map (fun x -> x * x * x)
那么它似乎做的是将List.Map放在后面(有趣的x - > x * x * x) 并且不会改变[2; 4; 6]
的位置所以现在它看起来像这样:
let result2 = [2;4;6] (fun x -> x * x * x) List.map
然而这不起作用。
我现在第一次学习f#。这在读一本关于f#的书时困扰着我。所以我可能会学到我后来失踪的东西,但无论如何我决定要问。
很明显,我错过了一些重要的东西。因为我可以轻松地重新创建管道操作员。但我不明白为什么它有效。当我了解更多信息时,我可能很快就会为自己感到尴尬。哦,好吧。
答案 0 :(得分:13)
管道运算符只是链式方法调用的语法糖。它与linq表达式在C#中的表达方式非常相似。
来自here的解释:
正向管道操作员 我喜欢这个人。 Forward管道运算符简单定义为:
let (|>) x f = f x
并且有一个类型签名:
'a -> ('a -> 'b) -> 'b
转换为:给定泛型类型'a,以及带'a并返回'b的函数,然后在输入上返回函数的应用程序。
让我举一个可以使用它的例子,而不是解释这个:
// Take a number, square it, then convert it to a string, then reverse that string
let square x = x * x
let toStr (x : int) = x.ToString()
let rev (x : string) = new String(Array.rev (x.ToCharArray()))
// 512 -> 1024 -> "1024" -> "4201"
let result = rev (toStr (square 512))
代码非常简单,但请注意语法看起来多么不守规矩。我们要做的就是获取一次计算的结果并将其传递给下一次计算。我们可以通过引入一系列新变量来重写它:
let step1 = square 512
let step2 = toStr step1
let step3 = rev step2
let result = step3
但现在你需要保持所有这些临时变量。 (|>)运算符的作用是获取一个值,并将其“转发”给函数,实质上允许您在函数调用之前指定函数的参数。这大大简化了F#代码,允许您将函数一起管道,其中一个函数的结果传递到下一个函数。因此,要使用相同的示例,代码可以清楚地写为:
let result = 512 |> square |> toStr |> rev
修改强>:
在F#中,您实际使用方法调用时正在执行一个函数,然后将其应用于后面的参数,因此在您的示例中,List.map (fun x -> x * x * x)
将应用于[2;4;6]
。管道操作员所做的就是以相反的顺序获取参数,然后将应用程序反转回来。
功能:List.map (fun x -> x * x * x)
参数:[2;4;6]
标准F#调用语法:f g
反向F#调用语法:g f
标准
let var = List.map (fun x -> x * x * x) [2;4;6]
反转:
let var = [2;4;6] |> List.map (fun x -> x * x * x)
答案 1 :(得分:8)
|>
周围的括号表示它是一个中缀运算符,因此您的示例可以写成
let result = (|>) [2;4;6] (List.map (fun x -> x * x * x))
由于|>
将第一个参数应用于第二个参数,因此等效于
let result = (List.map (fun x -> x * x)) [2;4;6]
答案 2 :(得分:5)
正如其他人上面所说,基本上你误解了结果2会解决的问题。它实际上会解决
List.map (fun x -> x * x * x) [2;4;6]
List.map有两个参数:一个应用于列表中所有元素和列表的函数。 (fun x -> x * x * x)
是第一个参数,[2;4;6]
是第二个参数。
基本上只是在右边的内容之后放置|>
左边的内容。
答案 3 :(得分:3)
如果在fsi中输入|>
的定义并查看由类型推断派生的运算符签名,您会注意到val ( |> ) : 'a -> ('a -> 'b) -> 'b
,即参数'a
被赋予函数{{1产生('a -> 'b)
。
现在将此签名投影到表达式'b
上,您将得到[2;4;6] |> List.map (fun x -> x * x * x)
,其中参数为list List.map (fun x -> x * x * x) [2;4;6]
,函数为partially applied一个参数的函数{ {1}}。