2010-11-17 77 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() 

問題是,當所有的值都是真實的,我按預期得到一個Some(true,true,true),但如果其中一個值傳入爲false,則foo爲空(!)。任何人ftw?

謝謝!

+2

'foo'實際上是'None',它只是'None'在運行時被表示爲'null'。 – Brian 2010-11-17 01:01:02

回答

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會話中,當我val時,它的打印爲None ......對於沒有空值的語言來說非常重要:)。謝謝你的回答,還有Brian。 – Alex 2010-11-17 15:12:44