【问题标题】:F# either monad (ROP) to to compose function with two parametersF# 使用 monad (ROP) 来组合具有两个参数的函数
【发布时间】:2017-01-12 16:51:52
【问题描述】:

我正在使用 chessie 辅助函数库来执行 ROP(单子) https://github.com/fsprojects/Chessie/blob/master/src/Chessie/ErrorHandling.fs

但是我不确定如何将以下三个函数简洁地组合在一起。只有当 func1 和 func2 返回成功时,才应评估 twoInputFunc

val func1 : int -> Result<Tp1, 'a>
val func2 : string -> Result<Tp2, 'a>
val twoInputFunc : par1:Tp1 -> Tpar2:Tp2 -> Result<Ta,'a>

【问题讨论】:

  • 我认为 Chessie 非常适合处理输入处理等需要经过一系列解析操作的事情。然而,如果你将它用于太多事情,它会使你的代码变得更丑 - 有一个棘手的平衡,但有时使用普通异常可能更容易(因为你完全避免了这种事情)。没有具体的例子很难说,但最好不要太虔诚:-)。

标签: f# functional-programming


【解决方案1】:

我认为这应该可行:

let f x y = trial {
    let! a = func1 x
    let! b = func2 y
    return! twoInputFunc a b}

想法是将每个结果绑定到ab,然后用作最后一个函数调用的输入。如果 func1 或 func2 导致错误,它将短路并返回错误。

另一种方法是使用应用程序:

let g x y = flatten (twoInputFunc <!> func1 x <*> func2 y)

在这里,您以 Applicative 样式应用两个参数,但最终会得到一个 Result of Result,因此您需要将其展平,这等效于 monad join 操作。

免责声明:我没有安装 Chessie,所以我没有尝试上面的代码,但我尝试了 FSharpPlus,它对所有 monad(不仅仅是 Either)都是通用的,它工作正常(改用 monad trialjoin 而不是 flatten)。

【讨论】:

  • 感谢工作。我会检查 F#+。您是否可以使用中缀运算符语法向我展示相同的内容?编辑刚刚看到你也添加了。
  • 啊,你的意思是应用程序,是的,我刚刚添加了它。
  • 感谢您的帮助。您能否建议我可以查看的任何 F# 开源项目,以便以惯用的方式查看这些概念。我大多只能看到简单的人为示例和函数库项目。
  • 不客气。 Fleeceapplicative styletraversable 中使用 Either monad。
  • 那么在这种情况下 func1 和 func2 是按顺序运行的吗?你会使用 f#+ 并行数组函数让它们并行运行吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
相关资源
最近更新 更多