3

trying to follow example in the expert f# book, and having an issue with the workflows...the code is as follows:

type Attempt<'a> = option<'a>
let succeed x    = Some (x)
let fail         = None 

let bind p rest  = 
    match p with 
    | None -> fail 
    | Some r -> rest r

let delay f = f()

type AttemptBuilder() = 

    member b.Return (x) = succeed x
    member b.Bind (p, rest) = bind p rest
    member b.Delay (f) = delay f
    member b.Let (p, rest):Attempt<'a> = rest p  //'
    member b.ReturnFrom x = x


// using it: 
let attempt = new AttemptBuilder()

let test foo = 
    attempt {
        if not foo then return! fail else return foo
    }

let check () = 
    attempt {

        let! n1 = test true
        let! n2 = test false
        let! n3 = test true
        let foo = n1,n2,n3
        return foo
    }
let foo = check ()

problem is , when all values are true, i get as expected, a Some(true, true, true), but if one of the values passed in is false, foo is null (!). Anyone ftw?

thanks!

Brian
  • 117,631
  • 17
  • 236
  • 300
Alex
  • 2,342
  • 1
  • 18
  • 30

1 Answers1

3

This is just because None is actually represented as null at runtime (see the remarks on the Option<'T> page on MSDN). Also, note that you can add

member x.Zero() = fail

to your builder, and then you can write test as

let test x = attempt { if x then return foo }

which is a little cleaner to my eyes.

kvb
  • 54,864
  • 2
  • 91
  • 133
  • ahh, you are right! actually, when i add a match for None to test foo, it is in fact None, however when i put a break point there, it is showing as null, even though in the fsi session, when i val it, it's printed as None... So much for language without nulls :). thanks for your answer, and Brian as well. – Alex Nov 17 '10 at 15:12