将值传递给管道中的第二个参数

Chr*_*sCa 1 f# pipeline

在管道中将值传递给函数的第二个参数的正确方法是什么?

例如

async {
    let! response =
        someData
        |> JsonConvert.SerializeObject
        |> fun x -> new StringContent(x)
        |> httpClient.PostAsync "/DoSomething"
        |> Async.AwaitTask
}

Run Code Online (Sandbox Code Playgroud)

上面的代码PostAsync中包含2个参数,即要发布到的url和要发布的内容。也尝试过后管和括号,但无法弄清楚该怎么做

有任何想法吗?

Fyo*_*kin 5

PostAsync具有非咖喱参数,不能一一传递,必须一次全部传递。这就是为什么您应该始终对参数进行管理的原因。

但是可惜,您无法控制的定义PostAsync,因为它是.NET库方法,因此您必须以一种或另一种方式包装它。有几种选择:

选项1:使用Lambda表达式:

|> fun body -> httpClient.PostAsync( "/DoSomething", body )
Run Code Online (Sandbox Code Playgroud)

选项2:使用咖喱参数声明一个函数

let postAsync client url body = 
    client.PostAsync(url, body)

...

|> postAsync httpClient "/DoSomething"
Run Code Online (Sandbox Code Playgroud)

通常,这是我的首选选项:在使用.NET API之前,我总是将它们包装为F#形式。这样更好,因为同一个包装器不仅可以转换参数,还可以转换其他内容,例如错误处理或您的情况下的异步模型:

let postAsync client url body = 
    client.PostAsync(url, body) 
    |> Async.AwaitTask
Run Code Online (Sandbox Code Playgroud)

选项3:变得超级通用,使自己成为将任何功能从非咖喱转化为咖喱的功能。在其他功能语言中,此类功能通常称为uncurry

let uncurry f a b = f (a, b)

...

|> uncurry httpClient.PostAsync "/DoSomething"
Run Code Online (Sandbox Code Playgroud)

一个问题是它仅适用于两个参数。如果您有一个带有三个参数的非咖喱函数,则必须为其创建一个单独的uncurry3函数,依此类推。