2016-03-06 39 views
3

我已經從Railway oriented programming複製驗證模塊,在我的應用程序執行的錯誤處理:編譯錯誤Kleisli組合物

type ErrorMessage = ErrorMessage of string 

type ValidationResult<'T> = 
    | Success of 'T 
    | Error of ErrorMessage 

module ValidationResult =  
    let doubleMap successHandler errorHandler = function 
     | Success x -> successHandler x 
     | Error e -> errorHandler e 

    let bind f = function 
     | Success x -> f x 
     | Error e -> Error e 

    let (>=>) f g = f >> bind g 

我通過使用下列測試功能測試Kleisli組合物:

let validation1 (list: int list) = 
    if List.length list = 6 
    then Success list 
    else Error <| ErrorMessage "Length error" 

let validation2 list = 
    if List.forall (fun x -> x > 6) list 
    then Success list 
    else Error <| ErrorMessage "All elements must be larger than 6" 

let combined = validation1 >=> validation2 
           //^^^^^^^^^^^^ compile error 

據我的理解,validation1validation2應該組成,因爲它們都是int list -> ValidationResult<int list>類型。然而,我得到了一個編譯錯誤

期待一種類型支持運算符'> =>',但給予函數 類型。您可能會錯過某個函數的參數。

我該如何解決這個問題?

+2

你忘了打開ValidationResult嗎? –

+0

@FyodorSoikin,來自我的一個愚蠢的錯誤......沒有意識到這很簡單。如果你把你的評論作爲答案,我會很樂意接受它。謝謝 – rexcfnghk

回答

6

看來你只是忘了open ValidationResult,所以你的構圖操作符不在範圍內。

對於一個正常的函數,F#會抱怨該符號未定義。但運營商是另一回事。

可以通過兩種方式定義運算符:作爲獨立函數(函數方式)或作爲傳遞給運算符的一種類型(.NET方式)的靜態成員。在前一種情況下,函數需要在作用域中可見,但在後一種情況下它不會:只要您設法將運算符定義爲靜態成員的對象得到保留,則不需要其類型可見。

這就是爲什麼F#表示它「期望類型支持運算符」而不是「函數未定義」。