Reputation: 91
I want a piping operator able to pipe as last parameter. For example, with this definitions:
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
}
I want to be able to write this code (suppose the operator is |&> ):
let downloadAndDecompress =
download |&> decompressStream |&> writeToTempFile
So I can compose functions, putting right side as last parameter (parameter scoped) of the left side of the operator. The operator should be left associative. So at the end, In my example, I would use downloadAndDecompress passing an url and I would get the temp filename with the decompressed content as result.
I'm trying with this code:
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
But, I cant get this to work.
So, is there some implementation of this semantics or something very similar? How can implement the custom binary piping operator?
Upvotes: 2
Views: 222
Reputation: 17038
OK, I think I figured this out. The operator you're describing is basically an infix version of what's usually called flip
:
let (|&>) f a b =
f b a
With that, you can define downloadAndDecompress
as:
let downloadAndDecompress =
download |&> (decompressStream |&> writeToTempFile)
The parentheses are needed because the operator is left-associative. Or you can eliminate the need for parens by using a right-associative operator instead, like this:
let (^&>) f a b =
f b a
let downloadAndDecompress =
download ^&> decompressStream ^&> writeToTempFile
Upvotes: 2