我正在尝试编写自己的 Either 构建器,作为我在 f# 中学习计算表达式的一部分,但我认为 Combine 方法存在问题,我遇到了困难。到目前为止我的代码:
type Result<'a> =
| Failure
| Success of 'a
type EitherBuilder() =
member this.Bind(m,f) =
match m with
| Failure -> Failure
| Success(x) -> f x
member this.Yield x =
Success(x)
member this.YieldFrom x =
x
member this.Combine(a,b) =
match a with
| Success(_) -> a
| Failure -> b()
member this.Delay y =
fun () -> y()
member this.Run(func) =
func()
使用此代码,我使用两个测试来测试组合:
let either = new EitherBuilder()
...
testCase "returns success from 3 yields" <|
fun _ ->
let value = either {
yield! Failure
yield 4
yield! Failure
}
value |> should equal (Success(4))
testCase "returns success with nested workflows" <|
fun _ ->
let value = either {
let! x = either {
yield! Failure
}
yield 5
}
value |> should equal (Success(5))
正如我所料,第一个测试通过,但第二个测试失败并显示以下消息:
抛出异常:nunit.framework.dll 中的“NUnit.Framework.AssertionException”通过嵌套工作流测试/返回成功:失败:预期:
<Success 5>
但是:<Failure>
我不明白。x
没有产生,那么为什么它会影响我的父工作流程?如果我移动让!下面产量测试通过。我盯着我的 Combine 实现,它在我看来,对于Failure*Success
pair,参数的实际顺序不会影响结果,但似乎确实如此