(まず、質問の「バインド」は関係ありませんstd::bind
)
私はExpected<T>の話を見て、このテクニックの歴史に関するプレゼンテーションには、Haskellでのこのことの背後にある核となるアイデアが欠けていると思いました。
Haskellの核となる考え方は、の値に「決して」アクセスしないということですExpected<T>
。Expected<T>
代わりに、の状態に応じて適用されるかどうかに応じて、ラムダをに渡しますExpected<T>
。
この「バインド」コンビネータ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>
ます。Either
これは、 Haskellでモナドを使用する標準的な方法です。
私が言ったように、確かに誰かがこれを見たに違いありません。
編集:callFun{1..3}に対して間違ったリターンタイプを記述しました。のさまざまな値ではExpected<T>
なく、を返します。これは、 orコンビネータの要点のようなものです。T
T
then
>>