What is the role of `while`-loops in computation expressions in F#?

后端 未结 1 769
旧时难觅i
旧时难觅i 2021-01-02 11:31

If you define a While method of the builder-object, you can use while-loops in your computation expressions. The signature of the While

相关标签:
1条回答
  • 2021-01-02 11:57

    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>.

    0 讨论(0)
提交回复
热议问题