1
foo { return! fooZero }

Is that what you mean?

By on 9/20/2009 10:47 AM ()

Hi,
I think 'return!' won't work here. The C# 'yield break' immediately terrminates the generated sequence. I don't think there is any way to do that in F#. If it was possible, I'd expect something like this:

1
2
3
 
seq { for i in 1 .. 10 do 
           if (i = 5) then return () }

... but this doesn't work, because 'return' isn't allowed inside sequence expressions. You could define your own sequence expression to do that (a little bit like this [link:tomasp.net] ), but sequence expressions are optimized, so you'd get really slow code.

So, I can't really give you any good answer here :-(. The only reasonable way to do this is to restructure the code, so that you don't need 'imperative' construct like yield break.

Tomas

By on 9/20/2009 11:02 AM ()

Brian,Nyeah. That's what I ended up doing, but it feels like a stopgap. I was looking for the code inside the computation expression to be independent of the actual computation builder. I was playing around with different variants, say ce0 and ce1, and it would be handy if I could just do search and replace on ce0 { -> ce1 { and everything would just work.Tomas,I was looking for something for computation expressions in general, but I guess the answer is the same. I disagree somewhat that using a computation expression's zero element is "evil and imperative".Note that e.g.

1
cexpr { let! x = blah() in if x = 0 then return 5 }

will insert the Zero element automatically for the else branch of the if statement. My particular case was, what to do when you have a match instead:

1
cexpr { let! x = blah() in match x with None -> return zero | _ -> return 5 }

I guess I'm looking for 'mzero' from Haskell's MonadPlus. It also looks unbalanced that there is syntactic sugar for everything but zero in F#'s computation expressions.thank you both,Kurt

By on 9/20/2009 11:23 PM ()

How about

foo { if false then failwith "never" }

then? Actually, even better, you can just do "()" as in e.g.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 

type Maybe<'a> = (unit -> 'a option)

let succeed x = (fun () -> Some(x)) : Maybe<'a>
let fail      = (fun () -> None) : Maybe<'a>
let runMaybe (a : Maybe<'a>) = a()
let bind p rest = match runMaybe p with None -> fail | Some r -> (rest r)
let delay f = (fun () -> runMaybe (f ()))

type MaybeBuilder() =
    member b.Return(x) = succeed x
    member b.Bind(p, rest) = bind p rest
    member b.Delay(f) = delay f
    member b.Zero() = fail
    
let maybe = new MaybeBuilder()

let r = maybe {
            match 1+1 with
            | 3 -> return 0
            | _ -> ()  // this is mzero
        }
printfn "%A" (r())
By on 9/21/2009 5:43 AM ()

Actually, even better, you can just do "()" as in e.g.

Ah! Perfect. Thanks a lot.Kurt

By on 9/21/2009 9:42 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper