编译Kleisli组合的错误

时间:2016-03-06 03:28:45

标签: f#

我有一个从Railway oriented programming复制的验证模块,它在我的应用程序中执行错误处理:

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>类型。但是我收到了编译错误

  

期望支持运营商的类型'&gt; =&gt;'但是给了一个功能   类型。您可能缺少函数的参数。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:6)

您似乎忘记了open ValidationResult,因此您的合成运算符不在范围内。

对于正常功能,F#会抱怨该符号未定义。但运营商是另一回事。

可以通过两种方式定义运算符:作为独立函数(函数方式)或作为传递给运算符的类型之一的静态成员(.NET方式)。在前一种情况下,函数需要在范围内可见,但在后一种情况下它并不是:只要你设法获得一个操作符被定义为静态成员的对象,你就不会这样做。需要让它的类型可见。

这就是为什么F#说它&#34;期望一个类型支持运营商&#34;而不是&#34;功能未定义&#34;。