gpt4 book ai didi

f# - 也许 monad 的 "opposite"有标准的 monad 吗?

转载 作者:行者123 更新时间:2023-12-04 13:05:16 25 4
gpt4 key购买 nike

也许 monad 允许链接一组可能失败的操作符(通过返回 None),最后返回 Some result如果每个子操作都成功,或者 None如果有任何失败。这是一个小的虚拟示例:

type MaybeBuilder() =
member this.Return(x) =
Some x
member this.Bind(m, f) =
match m with
| Some x -> f x
| None -> None

let maybe = MaybeBuilder()

let list = [1;2;3;4]

// evaluates to Some 3
maybe {
let! x1 = List.tryFind ((=) 1) list
let! x2 = List.tryFind ((=) 2) list
return x1 + x2
}

// evaluates to None
maybe {
let! x1 = List.tryFind ((=) 1) list
let! x2 = List.tryFind ((=) 6) list
return x1 + x2
}

这大致相当于:
// evaluates to Some 3
match List.tryFind ((=) 1) list with
| None -> None
| Some x1 ->
match List.tryFind ((=) 2) list with
| None -> None
| Some x2 -> Some (x1 + x2)

// evaluates to None
match List.tryFind ((=) 1) list with
| None -> None
| Some x1 ->
match List.tryFind ((=) 6) list with
| None -> None
| Some x2 -> Some (x1 + x2)

在我拥有的一段代码中,我目前正在执行与此相反的操作,返回第一个成功命中:
// evaluates to Some 1
match List.tryFind ((=) 1) list with
| Some x1 -> Some x1
| None ->
match List.tryFind ((=) 2) list with
| Some x2 -> Some x2
| None -> None

// evaluates to Some 2
match List.tryFind ((=) 6) list with
| Some x1 -> Some x1
| None ->
match List.tryFind ((=) 2) list with
| Some x2 -> Some x2
| None -> None

这也可以用 monad 来获得漂亮的计算表达式语法吗?

最佳答案

前段时间写了一篇博客,实现了imperative computation builder in F# .例如,下面是一个返回 0 并且从不执​​行 printfn 的计算。陈述:

let test() = imperative {
return 0
printfn "after return!"
return 1 }

我认为您的代码示例可以写为:
imperative { return! List.tryFind ((=) 1) list 
return! List.tryFind ((=) 2) list }

它是如何工作的?

正如您所建议的(Lee 也提到过),该类型也基于 option<'T>类型,略有不同,我使用的是延迟选项值(这样您就可以在不评估它们的情况下组合计算),因此 monadic 类型的类型实际上是:
type Imperative<'T> = unit -> option<'T>

计算构建器中的关键技巧是添加 Combine (其行为类似于 Lee 的 Haskell 版本中的 mplus)运行第一个计算并返回其结果(如果它是 Some )或运行其余的(如果它是 None )( ab这里实际上是函数 - 所以我们需要调用它们并延迟结果):
member x.Combine(a, b) = (fun () ->
match a() with
| Some(v) -> Some(v) // if it returned, we can return the result immediately
| _ -> b() ) // otherwise, we need to run the second part

它实际上工作得非常好 - 您可以添加对循环和异常处理的支持,如果您使类型更复杂,则可以添加其他功能,例如 break :
imperative { 
for x in 1 .. 5 do
if (x % 2 = 0) then do! continue
printfn "number = %d" x }

关于f# - 也许 monad 的 "opposite"有标准的 monad 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19384459/

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