最后一个参数是否有一些管道运算符或在 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
我想要一个管道操作员能够将管道作为最后一个参数。例如,使用以下定义:
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