理解F#组合运算符

air*_*tis 4 f# pointfree function-composition

我非常精通在F#中使用>><<运算符.然而,在查看F#源以建立更深入的理解之后,我对此感到困惑:

let inline (>>) f g x = g(f x)
let inline (<<) f g x = f(g x)
Run Code Online (Sandbox Code Playgroud)

我如何从概念上解释这些表达?另外,你会如何形容这些表达?他们定义了一种类型吗?

Gus*_*rra 5

我认为描述它的最佳方式是一个例子,因为查看定义可能会有点混乱.假设你有这个:

let isEven x = x % 2 = 0
[1 .. 99] |> List.filter (fun x -> not (isEven x))
Run Code Online (Sandbox Code Playgroud)

使用合成运算符,您可以将其重写为以下之一:

[1 .. 99] |> List.filter (isEven >> not)
[1 .. 99] |> List.filter (not << isEven)
Run Code Online (Sandbox Code Playgroud)

更通用的是,如果你有这样的东西:

data |> a |> b |> c
Run Code Online (Sandbox Code Playgroud)

你可以像这样重写它:

data |> (a >> b >> c)
Run Code Online (Sandbox Code Playgroud)

并解释a >> b >> c做a,然后做b,然后做c.如果您更喜欢更传统的向后排序:

(a (b (c data)))
Run Code Online (Sandbox Code Playgroud)

你可以把它重写为

((a << b << c) data)
Run Code Online (Sandbox Code Playgroud)

这也称为无点风格.在正常情况下,它可能比使用普通样式更难阅读,但是当传递到更高阶函数时,它可以更容易阅读,因为您可以避免添加(fun x -> )噪音.


Jwo*_*sty 3

正如F# 函数的 msdn 页面所说,“F# 中的函数可以由其他函数组合而成。两个函数 function1 和 function2 的组合是另一个函数,代表了 function1 的应用程序跟随 function2 的应用程序。”

它可以被认为与管道运算符类似,只是不指定最后一个/最深的参数;例如,以下两行是等效的:

let composed = f >> g
let piped x = g <| f x
Run Code Online (Sandbox Code Playgroud)

另请参阅问题以获取更多信息。