我有以下计算表达式。问题是 For/While 不循环。
type Internal<'T> = Internal of option<'T>
type Maybe<'T> = Maybe of Lazy< Internal<'T> >
type Delayed<'T> = Delayed of (unit -> Internal<'T>)
let run (Maybe f) = f.Force()
type MaybeBuilder() =
member this.Bind(m, f) = m |> bind f
member this.Return(x) = Internal (Some x)
member this.ReturnFrom(Maybe v) = v.Force()
member this.Zero() = Internal None
member this.Combine(a, g) = a |> combine g
member this.Delay(f) = f |> delay
member this.Run(f) = f |> run
member this.While(guard, Delayed body) =
if not ( guard() ) then this.Zero()
else ( body() ) |> bind ( fun () -> this.While(guard, Delayed body) )
member this.TryWith(Delayed body, handler) =
try this.ReturnFrom( Maybe ( lazy body() ) )
with e -> e |> handler
member this.TryFinally(Delayed body, compensation) =
try this.ReturnFrom( Maybe ( lazy body() ) )
finally compensation()
member this.Using(disposable : #System.IDisposable, body) =
let body' = fun () -> disposable |> body
this.TryFinally( Delayed body', fun () ->
match disposable with
| null -> ()
| disp -> disp.Dispose() )
member this.For(sequence : #seq<_>, body) =
let sequence' = sequence |> seq
this.Using( sequence'.GetEnumerator(), fun enum ->
this.While( enum.MoveNext, this.Delay( fun () -> enum.Current |> body ) ) )
我不确定这是"组合"问题还是什么,我非常感谢您的帮助。帮助程序函数在 MaybeBuilder 类型中定义:
let bind (f : 'T -> Internal<'U>) (Internal m) =
match m with
| None -> Internal None
| Some x -> x |> f
let combine (Delayed g) (Internal m) =
match m with
| Some _ -> Internal m
| None -> g()
let delay f = Delayed f
let run (Delayed f) =
let (Internal runResult) = f()
Maybe (lazy Internal runResult)
例如,下面的代码生成"j is 1",仅此而已。
let maybe = new MaybeBuilder()
let m7 : Maybe<int> =
maybe {
let sequence = seq [ 1 .. 13 ]
for j in sequence do
printfn "j is %i" j
}
到目前为止,将"While"的定义更改为以下内容似乎已经解决了这个问题。
member this.While(guard, Delayed body) =
if not ( guard() ) then this.Zero()
else body() |> combine ( Delayed ( fun () -> this.While(guard, Delayed body) ) )