2010-11-17 2 views
3

пытается последовать примеру в эксперт 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() 

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

спасибо!

+2

'foo' фактически' None', это просто, что 'None' представляется как' null' во время выполнения. – Brian

ответ

3

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

member x.Zero() = fail 

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

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

который немного чист мои глаза.

+0

ах, вы правы! на самом деле, когда я добавляю совпадение для None для проверки foo, это на самом деле None, однако, когда я помещаю точку останова там, он отображается как null, хотя в сеансе fsi, когда я его внял, он напечатан как None ... Так много для языка без нулей :). спасибо за ваш ответ, и Брайан. – Alex