What is the role of `while`-loops in computation expressions in F#?
computation-expression, f#, syntax
Solution
If you look at how computation expressions are evaluated, you'll see that
while foo() do
printfn "step"
yield bar()
is translated to something like
builder.While(fun () -> foo(),
builder.Delay(fun () ->
printfn "step"
builder.Yield(bar()))))
This translation allows the body of the while loop to be evaluated multiple times. While your type signatures are accurate for some computation expressions (such as `seq` or `async`), note that the insertion of the call to `Delay` may result in a different signature. For instance, you could define a list builder like this:
type ListBuilder() =
member x.Delay f = f
member x.While(f, l) = if f() then l() @ (x.While(f, l)) else []
member x.Yield(i) = [i]
member x.Combine(l1,l2) = l1 @ l2()
member x.Zero() = []
member x.Run f = f()
let list = ListBuilder()
Now you can evaluate an expression like:
list {
let x = ref 0
while !x < 10 do
yield !x
x := !x + 1
}
to get the equivalent of `[0 .. 9]`.
Here, our `While` method has the signature `(unit -> bool) * (unit -> 'a list) -> 'a list`, rather than `(unit -> bool) * 'a list -> 'a list`. In general, when the `Delay` operation has type `(unit -> M<'a>) -> D<M<'a>>`, the `While` method's signature will be `(unit -> bool) * D<M<'a>> -> M<'a>`.
Problem
If you define a `While` method of the builder-object, you can use `while`-loops in your computation expressions. The signature of the `While` method is: ``` member b.While (predicate:unit->bool, body:M<'a>) : M<'a> ``` For comparison, the signature of the `For` method is: ``` member b.For (items:seq<'a>, body:unit->M<'a>) : M<'a> ``` You should notice that, in the `While`-method, the body is a simple type, and not a function as in the `For` method. You can embed some other statements, like `let` and function-calls inside your computation-expressions, but those can impossibly execute in a `while`-loop more than once. ``` builder { while foo() do printfn "step" yield bar() } ``` Why is the `while`-loop not executed more than once, but merely repeated? Why the significant difference from for-loops? Better yet, is there some intended strategy for using while-loops in computation-expressions?