gpt4 book ai didi

f# - 如何在也许计算生成器中实现延迟?

转载 作者:行者123 更新时间:2023-12-04 03:12:52 27 4
gpt4 key购买 nike

这是我到目前为止的内容:

type Maybe<'a> = option<'a>

let succeed x = Some(x)

let fail = None

let bind rest p =
match p with
| None -> fail
| Some r -> rest r

let rec whileLoop cond body =
if cond() then
match body() with
| Some() ->
whileLoop cond body
| None ->
fail
else
succeed()

let forLoop (xs : 'T seq) f =
using (xs.GetEnumerator()) (fun it ->
whileLoop
(fun () -> it.MoveNext())
(fun () -> it.Current |> f)
)
whileLoop可以很好地支持 for循环,但是我看不到如何获得while循环支持。问题的部分原因是while循环的翻译使用了 delay,在这种情况下我无法弄清楚。下面明显的实现可能是错误的,因为它不会延迟计算,而是运行它!
let delay f = f()

没有延迟也阻碍了 try...withtry...finally

最佳答案

实际上,在F#中有两种不同的方法来实现延续构建器。一种是使用monadic类型表示延迟的计算(如果它支持某种表示延迟的计算的方式,例如Async<'T>或okt_code类型,如kkm所示)。

但是,您还可以使用F#计算表达式的灵活性,并使用其他类型作为unit -> option<'T>的返回值。然后,您需要相应地修改Delay操作并实现Combine成员,但这一切都可以很好地完成:

type OptionBuilder() = 
member x.Bind(v, f) = Option.bind f v
member x.Return(v) = Some v
member x.Zero() = Some ()
member x.Combine(v, f:unit -> _) = Option.bind f v
member x.Delay(f : unit -> 'T) = f
member x.Run(f) = f()
member x.While(cond, f) =
if cond() then x.Bind(f(), fun _ -> x.While(cond, f))
else x.Zero()

let maybe = OptionBuilder()

诀窍是,当您有需要延迟的计算时,F#编译器将使用 Run-即:1)包装整个计算,2)当您顺序组合计算时,例如在计算中使用 Delay并3)延迟 ifwhile的主体。

在上面的定义中, for成员返回 Delay而不是 unit -> M<'a>,但这很好,因为 M<'a>CombineWhile作为第二个参数。此外,通过添加评估函数的 unit -> M<'a>,可以评估 Run块(延迟函数)的结果,因为整个块都传递给 maybe { .. }:
// As usual, the type of 'res' is 'Option<int>'
let res = maybe {
// The whole body is passed to `Delay` and then to `Run`
let! a = Some 3
let b = ref 0
while !b < 10 do
let! n = Some () // This body will be delayed & passed to While
incr b
if a = 3 then printfn "got 3"
else printfn "got something else"
// Code following `if` is delayed and passed to Combine
return a }

这是一种为非延迟类型定义计算构建器的方法,这种方法最有可能比在函数内部包装类型更有效(如在kkm的解决方案中一样),并且不需要定义该类型的特殊延迟版本。

请注意,这个问题不会发生在Haskell,因为这是一种惰性语言,所以不需要显式延迟计算。我认为F#转换非常优雅,因为它可以处理延迟的类型(使用返回 RunDelay)和仅表示立即结果的类型(使用返回函数和 M<'a>Delay)。

关于f# - 如何在也许计算生成器中实现延迟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9041106/

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