(Прежде всего "bind" в вопросе не имеет ничего общего с std::bind
)
Я просмотрел Ожидаемый <T> говорить, и я подумал, что в презентации этой истории отсутствует основная идея этой вещи в Haskell.
Основная идея в Haskell заключается в том, что вы "никогда" не используете значение Expected<T>
. Вместо этого вы принимаете лямбда для 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
возвращает a Expected<Baz>
, callFun2
возвращает a Expected<Bar>
, а callFun3
возвращает a Expected<Foo>
.
Как вы можете видеть, этот код не проверяет наличие ошибок. Ошибки прекратят выполнение, но они все еще имеют все преимущества Expected<T>
. Это стандартный способ использования монады Either
в Haskell.
Как я уже сказал, наверняка кто-то, должно быть, посмотрел на это.
Изменить: я написал неправильные типы возврата для callFun {1..3}. Они возвращают Expected<T>
, а не T
для различных значений T
. Это своего рода целая точка комбинатора then
или >>
.