编译Kleisli组合的错误

rex*_*ghk 3 f#

我有一个从面向铁路的编程复制的验证模块,它在我的应用程序中执行错误处理:

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
Run Code Online (Sandbox Code Playgroud)

我正在使用以下测试函数测试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
Run Code Online (Sandbox Code Playgroud)

根据我的理解,validation1并且validation2应该撰写因为两者都是类型int list -> ValidationResult<int list>.但是我遇到了编译错误

期望一个支持运算符'> =>'的类型但给定一个函数类型.您可能缺少函数的参数.

我怎么解决这个问题?

Fyo*_*kin 6

您似乎忘记了open ValidationResult,因此您的合成操作符不在范围内.

对于正常函数,F#会抱怨符号未定义.但运营商是另一回事.

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

这就是为什么F#说它"期望一个类型支持运算符"而不是"函数未定义"的原因.