内置f#运算符来组合具有相同输入但输出不同的功能?

Phi*_*ett 2 f# functional-programming

我理解<< compose运算符有两个函数,它们都接受并返回相同的类型.例如 (lhs:'a -> 'a) -> (rhs:'a -> 'a) -> 'a

我经常发现自己想要的东西就像(lhs:'a -> 'b) -> (rhs:'c -> 'b) -> 'b我对副作用感兴趣而不是返回值'b可能是单位类型.这只是当我连续两行,我坚持到数据库的时候.

是否有内置函数或惯用F#方式,无需编写类似的东西

let myCompose lhs rhs arg =
    lhs arg
    rhs arg
Run Code Online (Sandbox Code Playgroud)

byt*_*ter 5

后向合成运算符(<<)定义为:

( << ) : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c`
Run Code Online (Sandbox Code Playgroud)

在应用了两个谓词的情况下,它实际上是一个函数,它接受'a返回的初始值'c,而在'b内部处理值.

从您提供的代码示例中,让我假设您需要为两个谓词应用参数.做这件事有很多种方法:

丢弃(第一个)谓词返回的值,而是返回原始参数.WebSharper中存在这样的运算符:

let ( |>! ) x f = f x; x
// Usage:
let ret =
    x
    |>! f1
    |>! f2
    |> f3
Run Code Online (Sandbox Code Playgroud)

我喜欢这种方法,因为:

  • 它不会使事情复杂化; 每个函数应用程序都是原子的,代码看起来更具可读性;
  • 它允许链接三个或更多谓词,如上例所示;

在这种情况下,f必须返回unit,但您可以轻松地解决这个问题:

let ( |>!! ) x f = ignore(f x); x
Run Code Online (Sandbox Code Playgroud)

将参数应用于两个谓词,返回结果元组,与您自己的示例完全相同.有这样的运营商OCaml,很容易适应F#:

val (&&&) : ('a -> 'b) -> ('a -> 'c) -> 'a -> 'b * 'c
Run Code Online (Sandbox Code Playgroud)

正如@JackP注意到的,&&&已经在F#中定义了另一个目的,所以让我们使用另一个名字:

/// Applying two functions to the same argument.
let (.&.) f g x = (f x, g x)

// Usage
let ret1, ret2 =
   x
   |> (f .&. g)
Run Code Online (Sandbox Code Playgroud)

注意以上示例适用于功能应用的直接顺序.如果需要以相反的顺序应用它们,则需要相应地修改代码.