【问题标题】:Using bind and Kliesli composition operators with Result将 bind 和 Kliesli 组合运算符与 Result 一起使用
【发布时间】:2022-01-14 19:04:29
【问题描述】:

我正在尝试将绑定 (>>=) 和 Kleisli 组合 (>=>) 运算符与基本 Result 类型一起使用,但它们要么未定义,要么不在范围内:

let f x =
  if x%2 = 0 then Ok (x/2)
  else            Error ()

let ff x = Ok x >>= f >>= f
let ff' = f >=> f

[<EntryPoint>]
let main _ =
  printfn "%A" (ff 12)
  printfn "%A" (ff' 28)
  0

错误 FS0043 需要一个支持运算符“>>=”的类型,但给定了一个函数类型。您可能缺少函数的参数。

我尝试open 几个不同的命名空间来将定义纳入范围,但没有成功。

this 看来,如果没有扩展,通常无法定义运算符,但在任何地方都有标准Result 的定义吗?

【问题讨论】:

    标签: f# monads


    【解决方案1】:

    F# 核心库中没有定义类似 Haskell 的运算符,它们也不太可能定义。您需要在自己的序曲中编写它们,或者使用像 FSharpPlus 这样的库来实现这些和其他更类似于 Haskell(嗯,类型级别)的编程方法。

    【讨论】:

      【解决方案2】:

      除了 Phillip 在他的回答中所说的之外,补充一下您可以使用内置的 Result.bind 操作和函数组合或管道来重写您的示例可能会很有用:

      let f x =
        if x%2 = 0 then Ok (x/2)
        else Error ()
      
      let ff x = Ok x |> Result.bind f |> Result.bind f
      let ff' = f >> Result.bind f
      
      printfn "%A" (ff 12)
      printfn "%A" (ff' 28)
      

      这当然只是一个玩具示例,所以很难说你真正想要做什么,但如果我尝试使用 Result,我的首选将是使用标准库函数 - 它们可能会您的代码更长,但可以说它更具可读性。

      【讨论】:

      • 这是一个熟悉的问题。就我个人而言,我发现 Haskell &gt;&gt;= 运算符非常易读。
      • 当我希望其他编码人员(或未来的我)注意到我期望 Result&lt;'a,'b&gt; 时,我使用 Result.bind(或类似的)。当我希望其他编码人员(或未来的我)专注于绑定函数时,我使用 &gt;&gt;=(或类似的),而不是我们所在的 monad。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      • 2020-04-22
      • 2017-11-17
      • 2013-09-10
      相关资源
      最近更新 更多