【问题标题】:Compile error for Kleisli compositionKleisli 组合的编译错误
【发布时间】:2016-03-06 03:28:45
【问题描述】:

我有一个从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 -&gt; ValidationResult&lt;int list&gt; 类型。但是我得到了一个编译错误

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

我该如何解决这个问题?

【问题讨论】:

  • 你忘记open ValidationResult了吗?
  • @FyodorSoikin,我犯了一个多么愚蠢的错误……没想到事情这么简单。如果您将评论作为答案,我将很乐意接受。谢谢

标签: f#


【解决方案1】:

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

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

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

这就是为什么 F# 说它“期望支持类型的运算符”而不是“函数未定义”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 2017-03-23
    • 2018-04-13
    • 1970-01-01
    相关资源
    最近更新 更多