gpt4 book ai didi

f# - 面向铁路的编程和部分应用

转载 作者:行者123 更新时间:2023-12-04 18:00:46 24 4
gpt4 key购买 nike

当我必须处理 IO/解析字符串/...时,我喜欢使用 ROP

但是,假设我有一个带有 2 个参数的函数。当您的 2 个参数已经是 Result<'a,'b> (不需要相同的 'a, 'b)时,如何进行干净/可读的部分应用程序?

现在,我所做的是使用元组传递参数并使用下面的函数来获取元组的结果,这样我就可以将我的函数与这个“元组参数”绑定(bind)。

/// Transform a tuple of Result in a Result of tuple
let tupleAllResult x =
match (fst x, snd x) with
| Result.Ok a, Result.Ok b -> (a,b) |> Result.Ok
| Result.Ok a, Result.Error b -> b |> Result.Error
| Result.Error a, _ -> a |> Result.Error

let f (a: 'T, b: 'U) = // something

(A, B) |> tupleAllResult
|> (Result.bind f)

有什么好主意吗?

这是我写的,有效但可能不是最优雅的
let resultFunc (f: Result<('a -> Result<'b, 'c>), 'd>) a =
match f with
| Result.Ok g -> (g a) |> Result.Ok |> Result.flatten
| Result.Error e -> e |> Result.Error |> Result.flatten

最佳答案

我在您的示例中没有看到部分应用,这是一个与柯里化(Currying)和参数传递相关的概念——这就是为什么我假设您在单子(monad) apply 之后。 , 因为你想转换一个包装为 Result 的函数值转换为一个函数,该函数采用 Result并返回另一个 Result .

let (.>>.) aR bR = // This is "tupleAllResult" under a different name
match aR, bR with
| Ok a, Ok b -> Ok(a, b)
| Error e, _ | _, Error e -> Error e
// val ( .>>. ) : aR:Result<'a,'b> -> bR:Result<'c,'b> -> Result<('a * 'c),'b>

let (<*>) fR xR = // This is another name for "apply"
(fR .>>. xR) |> Result.map (fun (f, x) -> f x)
// val ( <*> ) : fR:Result<('a -> 'b),'c> -> xR:Result<'a,'c> -> Result<'b,'c>

与您的问题不同的是 map而不是 bind在最后一行。

现在你可以开始 lift 函数到 Result世界:
let lift2 f xR yR =
Ok f <*> xR <*> yR
// val lift2 :
// f:('a -> 'b -> 'c) -> xR:Result<'a,'d> -> yR:Result<'b,'d> -> Result<'c,'d>

let res : Result<_,unit> = lift2 (+) (Ok 1) (Ok 2)
// val res : Result<int,unit> = Ok 3

关于f# - 面向铁路的编程和部分应用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55238701/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com