2016-03-26 48 views
2

我有以下計算表達式生成器:零和計算表達式組合

type ExprBuilder() = 
    member this.Return(x) = 
     Some x 

let expr = new ExprBuilder() 

我理解的方法返回目的,聯合,但我不明白是什麼表達式之間的區別如下所示:

let a = expr{ 
    printfn "Hello" 
    return 1 
} // result is Some 1 

let c = expr{ 
    return 1 
    printfn "Hello" 
} // do not compile. Combine method required 

我也不明白爲什麼在第一種情況下方法中不需要printfn聲明?

回答

4

在第一個表達式中,執行一些計算結果的值爲1,就是這樣。您不需要Zero,因爲Zero僅用於return -less表達式(這就是爲什麼它被稱爲「零」 - 當什麼都沒有的時候它就是這樣),而且您的表達式確實有return

要特別回答您的問題,Zero不需要「」,因爲printfn語句「不是所有表達式中的行都被轉換。編譯計算表達式時,編譯器將其分解爲「特殊」點,例如let!,do!return等,這些點之間的所有其餘代碼保持不變。在這種情況下,您的printfn調用只是成爲在return之前執行的代碼的一部分。

在第二個表達式中,執行計算:在值1的第一個結果,並在Zero秒一個結果(當表達缺乏return其隱含地假設)。但是整個計算表達式不能有兩個返回值,它必須有一個。因此,爲了將兩次計算的結果放在一起(可能會說,合併了),您需要使用Combine方法。

除了CombineZero,你也需要實現Delay這個工作。多部分(即「組合」)計算也被包裝在Delay中,以便允許構建器推遲評估並可能丟棄實現中的一些部分。

我推薦通過Scott Wlaschin的this introduction閱讀,特別是part 3 about Delay and Run