现在,我知道可以将第一行代码缩短为第二行。这是我第一次遇到它,找不到关于该运算符的任何文档。它是一个抽象概念,也可以用于其他事物吗?
let contains optValue value =
Option.exists (fun v -> v >= value) optValue
let contains optValue value =
Option.exists ((>=) value) optValue
答案 0 :(得分:5)
您已经被告知,第二个示例应该是(=)
,以使两个功能等效,因此,我不再赘述。但我想警告您,以这种方式使用>=
运算符可能会与您期望的工作方式不同。根本原因与F#如何进行部分应用有关,https://fsharpforfunandprofit.com/series/thinking-functionally.html是对此的最佳参考。 (相关部分是有关currying和部分应用程序的文章,但您需要按顺序阅读整篇文章,因为后面的文章是基于前面文章中介绍的概念构建的。)
现在,如果您已经阅读了这些文章,就会知道F#允许部分应用函数:如果您有两个参数的函数f a b
,但是仅使用一个参数f a
进行调用,结果是一个期望参数b
的函数,并且在接收到该函数时将执行f a b
。将运算符括在括号中时,F#会将其视为函数,因此,在执行(>=) value
时,您会得到一个正在等待第二个参数x
的函数,然后将对(>=) value x
求值。而且,当F#计算(op) a b
时,无论运算符是什么,它都与a op b
相同,因此(>=) value x
与value >= x
相同。
一开始,这就是大多数人不满意的地方。因为当您阅读Option.exists ((>=) value) optValue
时,您自然会想读为“该选项是否包含大于或等于value
的东西”?但是实际上,实际上是在说“选项是否包含值x
使得value >= x
为真?”,即小于或等于 {{1} }。
因此,连续应用的简单部分应用规则可能会导致大于或小于运算符,或者实际上是任何非可交换运算符,从而导致意外结果。请注意这一点,如果您想将部分应用程序与非交换运算符一起使用,请仔细检查您的逻辑。