为什么使用向后管道运算符可以解决编译错误?
Why does using a backwards pipeline operator resolve a compilation error?
编译器接受以下行:
input |> Prop.forAll <| fun (a , b) -> add a b = add b a
但是,当我用括号替换向后的管道运算符时,我收到错误消息:
input |> Prop.forAll ( fun (a , b) -> add a b = add b a )
Type mismatch. Expecting a
Arbitrary -> 'a but given a
('b -> 'c) -> Property The type 'Arbitrary' does not match the type ''a -> 'b
我不太清楚这个错误是什么意思。为什么向后管道运算符编译但括号不编译?
附录:
module Arithmetic
let add a b =
a + b
open FsCheck
open FsCheck.Xunit
[<Property(MaxTest=1000, QuietOnSuccess=true)>]
let ``'a + 'b equals 'b + 'a`` () =
// Declare generators per type required for function
let intGenerator = Arb.generate<int>
// Map previously declared generators to a composite generator
// to reflect all parameter types for function
let compositeGenerator = (intGenerator , intGenerator) ||> Gen.map2(fun a b -> a , b)
// Pull values from our composite generator
let input = Arb.fromGen compositeGenerator
// Apply values as input to function
input |> Prop.forAll <| fun (a , b) -> add a b = add b a
在第二行,你的参数顺序错误。
函数应用程序具有最高的优先级,因此首先应用它,然后再进行其他操作。运算符 <|
和 |>
在其后应用,它们具有相同的优先级,因此先应用左边的,然后应用右边的。所以如果你考虑这一行:
x |> y <| z
首先你应用左边的管道并得到:
(y x) <| z
应用正确的管道后,您将得到:
y x z
但是如果你考虑第二行,情况正好相反:
x <| y (z)
应用管道后:
y (z) x
input
应该是第一个arg,所以简单
Prop.forAll input (fun (a , b) -> add a b = add b a)
管道运算符起作用的原因是前向管道改变了解析顺序中的亲和力。
input |> Prop.forAll (fun (a , b) -> add a b = add b a)
~
input |> (Prop.forAll (fun (a , b) -> add a b = add b a))
~
Prop.forAll (fun (a , b) -> add a b = add b a) input
不编译。向后的管道将其改回。
input |> Prop.forAll <| fun (a , b) -> add a b = add b a
~
(input |> Prop.forAll) <| (fun (a , b) -> add a b = add b a)
~
(Prop.forAll input) (fun (a , b) -> add a b = add b a)
~
Prop.forAll input (fun (a , b) -> add a b = add b a)
哪个有。
FWIW 您提供的示例中的所有管道运算符似乎混淆了事情而不是帮助。通常不建议单行使用管道,除非它有助于您的自动完成。
Prop.forAll
函数的类型为 Arbitrary<'a> -> ('a -> 'b) -> Property
。这意味着 第一个 参数必须是一个 Arbitrary
,而下一个参数必须是一个函数 ('a -> 'b)
.
当您编写 input |> Prop.forAll (fun (a , b) -> add a b = add b a )
时,您试图用 (fun (a , b) -> add a b = add b a )
调用 Prop.forAll
,编译器试图将其解释为部分应用的函数。
由于 Prop.forAll
的第一个参数是 Arbitrary<'a>
,编译器试图将函数推断为 Arbitrary
,但事实并非如此。
编译器接受以下行:
input |> Prop.forAll <| fun (a , b) -> add a b = add b a
但是,当我用括号替换向后的管道运算符时,我收到错误消息:
input |> Prop.forAll ( fun (a , b) -> add a b = add b a )
Type mismatch. Expecting a Arbitrary -> 'a but given a ('b -> 'c) -> Property The type 'Arbitrary' does not match the type ''a -> 'b
我不太清楚这个错误是什么意思。为什么向后管道运算符编译但括号不编译?
附录:
module Arithmetic
let add a b =
a + b
open FsCheck
open FsCheck.Xunit
[<Property(MaxTest=1000, QuietOnSuccess=true)>]
let ``'a + 'b equals 'b + 'a`` () =
// Declare generators per type required for function
let intGenerator = Arb.generate<int>
// Map previously declared generators to a composite generator
// to reflect all parameter types for function
let compositeGenerator = (intGenerator , intGenerator) ||> Gen.map2(fun a b -> a , b)
// Pull values from our composite generator
let input = Arb.fromGen compositeGenerator
// Apply values as input to function
input |> Prop.forAll <| fun (a , b) -> add a b = add b a
在第二行,你的参数顺序错误。
函数应用程序具有最高的优先级,因此首先应用它,然后再进行其他操作。运算符 <|
和 |>
在其后应用,它们具有相同的优先级,因此先应用左边的,然后应用右边的。所以如果你考虑这一行:
x |> y <| z
首先你应用左边的管道并得到:
(y x) <| z
应用正确的管道后,您将得到:
y x z
但是如果你考虑第二行,情况正好相反:
x <| y (z)
应用管道后:
y (z) x
input
应该是第一个arg,所以简单
Prop.forAll input (fun (a , b) -> add a b = add b a)
管道运算符起作用的原因是前向管道改变了解析顺序中的亲和力。
input |> Prop.forAll (fun (a , b) -> add a b = add b a)
~
input |> (Prop.forAll (fun (a , b) -> add a b = add b a))
~
Prop.forAll (fun (a , b) -> add a b = add b a) input
不编译。向后的管道将其改回。
input |> Prop.forAll <| fun (a , b) -> add a b = add b a
~
(input |> Prop.forAll) <| (fun (a , b) -> add a b = add b a)
~
(Prop.forAll input) (fun (a , b) -> add a b = add b a)
~
Prop.forAll input (fun (a , b) -> add a b = add b a)
哪个有。
FWIW 您提供的示例中的所有管道运算符似乎混淆了事情而不是帮助。通常不建议单行使用管道,除非它有助于您的自动完成。
Prop.forAll
函数的类型为 Arbitrary<'a> -> ('a -> 'b) -> Property
。这意味着 第一个 参数必须是一个 Arbitrary
,而下一个参数必须是一个函数 ('a -> 'b)
.
当您编写 input |> Prop.forAll (fun (a , b) -> add a b = add b a )
时,您试图用 (fun (a , b) -> add a b = add b a )
调用 Prop.forAll
,编译器试图将其解释为部分应用的函数。
由于 Prop.forAll
的第一个参数是 Arbitrary<'a>
,编译器试图将函数推断为 Arbitrary
,但事实并非如此。