Проблема с вычислительным рабочим процессом

пытаясь следовать примеру в книге эксперта f # и имея проблему с рабочими процессами... код выглядит следующим образом:

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 ()

проблема в том, что когда все значения верны, я получаю, как и ожидалось, Some(true, true, true), но если одно из переданных значений ложно, foo равно null (!). Кто-нибудь фтв?

Спасибо!


person Alex    schedule 17.11.2010    source источник
comment
foo на самом деле None, просто None во время выполнения представляется как null.   -  person Brian    schedule 17.11.2010


Ответы (1)


Это просто потому, что None на самом деле представляется как null во время выполнения (см. примечания к Option<'T> страницу в MSDN). Также обратите внимание, что вы можете добавить

member x.Zero() = fail

своему строителю, а затем вы можете написать тест как

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

что немного чище для моих глаз.

person kvb    schedule 17.11.2010
comment
ааа, ты прав! на самом деле, когда я добавляю совпадение для None для проверки foo, на самом деле это None, однако, когда я ставлю точку останова, оно отображается как null, хотя в сеансе fsi, когда я его оцениваю, оно печатается как None ... Вот вам и язык без нулей :). спасибо за ваш ответ, и Брайан тоже. - person Alex; 17.11.2010