Some time ago I wrote a blog that implements an imperative computing builder in F # . For example, the following calculation, which returns 0 and never executes the printfn :
let test() = imperative { return 0 printfn "after return!" return 1 }
I think your sample code can be written as:
imperative { return! List.tryFind ((=) 1) list return! List.tryFind ((=) 2) list }
How it works?
As you suppose (and Lee mentioned this), the type is also based on the option<'T> , with the slight difference that I use the value of the parameter with a delay (so you can make calculations without evaluating them) so the type of monadic type is actually :
type Imperative<'T> = unit -> option<'T>
The key trick in the calculation builder is to add Combine (which behaves like mplus in the version of Lee Haskell), which starts the first calculation and returns its result (if it was Some ) or starts the rest (if it was None ) (both a and b on the are functions here, so we need to call them and delay the result):
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
It really works very well - you can add support for loops and exception handling, and if you make the type more complex, you can add other functions like break :
imperative { for x in 1 .. 5 do if (x % 2 = 0) then do! continue printfn "number = %d" x }
source share