为什么F#中换行符的效果对于某些表达式是不同的,并且(可以说)在某些表达式中反直觉?

Abe*_*bel 3 f# boolean operator-precedence

免责声明/编辑:这是一个相当简单的问题,但我问它,因为我(仍然)常常被F#中的评估顺序混淆,特别是.关于换行与空格.试验和错误总能让我到达我想要的地方,但如果您不得不求助于试错,我认为您不能真正理解某种语言.

如果我写:

let res x =
    x * 1 = x
    |> ignore
Run Code Online (Sandbox Code Playgroud)

一切都很好,但如果我写:

let res x =
    x * 1 = x && x * -1 = -x
    |> ignore
Run Code Online (Sandbox Code Playgroud)

然后编译器抱怨(它表示它预期bool -> bool,而不是bool -> unit).我原以为新线在这里充当分隔符.

添加括号有帮助,并将它放在一行显示它被评估为(X && (Y |> Z)),where XY是布尔表达式,Z是任何函数.

这是真的?有没有更简单的方法来找到它?或者更好的是,什么时候空白是一个重要的运算符,什么时候不是?


举另一个例子:

let v = x |> fun x -> float x |> fun y -> true
Run Code Online (Sandbox Code Playgroud)

为什么y这里的类型为float而不是类型int -> float?这可能是显而易见的,我确实已经编程了数千条线路,它甚至感觉很自然,但为什么呢?

如果给出的唯一答案是"运算符优先级并且->在之前|>",那么就这样吧.但我想/希望有更多的学术或其他形式,但背后的所有这些(我仍然觉得奇怪,&&prio低于|>,再次,我不明白为什么,在这种情况下,它感觉反直觉).

Gus*_*Gus 6

看看https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/symbol-and-operator-reference/#operator-precedence它似乎&&具有更高的优先级,|>因此你的猜测是正确的你需要添加括号:

let res x =
  (x * 1 = x && x * -1 = -x)
  |> ignore
Run Code Online (Sandbox Code Playgroud)

看起来新行不作为分隔符,除非它具有let绑定或属于此处列出的规则之一

例如,如果你采用这个表达式:

let res = 
  5 + 1
    .GetType()
Run Code Online (Sandbox Code Playgroud)

您还会收到错误,因为它将.操作符应用于1整个表达式,因此无论换行符如何,优先级规则仍然保留.