最后一个参数是否有一些管道运算符或在 F# 中定义它的方法?

Is there some pipe operator to last argument or a way to define it in F#?

我想要一个管道操作员能够将管道作为最后一个参数。例如,使用以下定义:

let download  (uri: String) scoped  =
    use client = new HttpClient()
    task {
        let! stream = client.GetStreamAsync(uri)
        let! r = scoped stream
        return r
    }

let decompressStream stream scoped   =
    use decompressedStream = new GZipStream(stream, CompressionMode.Decompress)
    task {
        let! r = scoped decompressedStream
        return r
    }

let writeToTempFile (stream: Stream) =
    let fileName = Path.GetTempFileName()
    use fileStream = File.OpenWrite(fileName)
    task {
        do! stream.CopyToAsync(fileStream)
        return fileName
    }

我希望能够编写这段代码(假设运算符是 |&> ):

let downloadAndDecompress =
    download |&> decompressStream |&> writeToTempFile

所以我可以编写函数,将右侧作为运算符左侧的最后一个参数(参数范围)。运算符应该保持关联。所以最后,在我的示例中,我将使用 downloadAndDecompress 传递一个 url,然后我将获得包含解压缩内容的临时文件名。

我正在尝试使用此代码:

type LastPipedArg = 
    static member inline (|&>)( f: 'a1 -> 'r, lastArg: 'a1) =
        f lastArg

    static member inline (|&>)(f: 'a1 -> 'a2 -> 'r, lastArg: 'a2) =
        fun a1 -> f a1 lastArg

    static member inline (|&>)( f: 'a1 -> 'a2 -> 'a3 -> 'r, lastArg: 'a3) =
        fun a1 a2 -> f a1 a2 lastArg
        
    static member inline (|&>)(f: 'a1 -> 'a2 -> 'a3 -> 'a4-> 'r, lastArg: 'a4) =
        fun a1 a2 a3 -> f a1 a2 a3 lastArg

但是,我无法让它工作。

那么,是否有此语义的一些实现或非常相似的东西?如何实现自定义二元管道运算符?

好的,我想我明白了。您描述的运算符基本上是通常称为 flip:

的中缀版本
let (|&>) f a b =
    f b a

这样,您可以将 downloadAndDecompress 定义为:

let downloadAndDecompress =
    download |&> (decompressStream |&> writeToTempFile)

括号是必需的,因为运算符是左结合的。或者您可以通过使用右关联运算符来消除对括号的需求,如下所示:

let (^&>) f a b =
    f b a

let downloadAndDecompress =
    download ^&> decompressStream ^&> writeToTempFile