首先,“bind”与
在Haskell中,核心思想是“永远不要”访问
我本以为这个“bind”组合器会成为
这个组合器的作用是将一系列函数连接在一起,而无需检查错误,并且第一个失败的函数将使评估短路。
或者使用这种语法,它开始类似于Haskell中使用的`>>=`运算符。
std::bind
无关。我看了一下Expected<T>的讲解,认为其中缺失了Haskell中这种技术背后的核心思想。在Haskell中,核心思想是“永远不要”访问
Expected<T>
的值。相反,你需要将一个lambda表达式传递给Expected<T>
,根据Expected<T>
的状态来确定是否应用该表达式。我本以为这个“bind”组合器会成为
Expected<T>
主要的使用方法,所以我想问一下,这种编程风格是否因某些原因被拒绝了。在下文中,我将称呼该组合器为then
。template <class T> class Expected<T> {
....
template <class V, class F> Expected<V> then(F fun_) {
if (!valid()) {
return Expected<V>::fromException(this(??)); // something like that
}
return fun_(get());
}
}
这个组合器的作用是将一系列函数连接在一起,而无需检查错误,并且第一个失败的函数将使评估短路。
auto res = Expected<Foo>::fromCode([]() { return callFun1(...); })
.then([](Baz& val) { return callFun2(..,val,..); })
.then([](Bar& val) { return callFun3(val,...); });
或者使用这种语法,它开始类似于Haskell中使用的`>>=`运算符。
auto res = []() { return callFun1(...); }
>> [](Baz& val) { return callFun2(..,val,..); }
>> [](Bar& val) { return callFun3(val,...); };
callFun1
返回一个 Expected<Baz>
,callFun2
返回一个 Expected<Bar>
,而 callFun3
返回一个 Expected<Foo>
。
正如您所看到的,这段代码没有检查错误。 错误会停止执行,但它们仍然具有 Expected<T>
的所有优点。 这是在 Haskell 中使用 Either
monad 的标准方式。
就像我说的那样,肯定有人已经看过这个问题了。
编辑:我为 callFun{1..3} 写错了返回类型。 它们返回各种值的 Expected<T>
,而不是 T
。 这就是 then
或 >>
combinator 的全部意义所在。
some_expected.then(static_cast<R(*)(Args...)>(&some_overloaded_function))
,或者使用lambda表达式,因为它们是单态的,可以看作是伪装的转换。 :| - Xeo