Is it possible to put together a computation expression builder that can sequence two or more expressions without putting do!
in front of each one?
If I've read the relevant section of the manual correctly, this should be possible through the builder's Combine
method. However, my Combine
method doesn't appear to be used; instead, I get a compiler warning suggesting that I use ignore
to discard the result.
For instance, given an F# State monad, I'd like to be able to do this:
let hello who = State (fun lines -> lines @ [sprintf "hello %s" who])
let m = state {
hello "world"
hello "F#"
}
let l = Execute m []
// l should now contain ["hello world"; "hello F#"]
In addition to what Dario wrote, you cannot redefine the usual sequencing to behave as monadic do!
(even if you decided not to support non-monadic operations in your computations). The problem is that usual sequencing isn't handled in any special way by the translator, so there is no interception point that you could use. Your example will be translated like this:
let m = state.Delay(fun () ->
hello "world"
hello "F#"
state.Zero())
The call to hello
is not wrapped into any member call that could be redefined.
In an earlier version of F# sequencing used to be translated to calls to Let
member like this:
let m = state.Delay(fun () ->
state.Let(hello "world", fun _ ->
state.Let(hello "F#", fun _ ->
state.Zero())))
So it was possible to do what you wanted, but it cannot be done in the current version (I believe one reason was that this adds too much wrapping which hurts the performance).
No, because that's what regular do
is for. If you want monadic do, i.e. do!
, you have to be explicit. Example:
let m = state {
printfn "World"
hello "World"
return 42
}
printfn
expression is of type unit
, and there is a do printfn
implicit.hello
case? We'd need monadic binding!Now how would the compiler know what to choose, do
or do!
? Maybe by types (Scala does this), but right now, it doesn't. So it just assumes a regular do
anywhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With