为什么使用向后管道运算符可以解决编译错误?

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,但事实并非如此。