开发者

Omit 'do!' in computation expression

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
}
  • The printfn expression is of type unit, and there is a do printfn implicit.
  • And in the 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜