Closed basiliscos closed 7 years ago
Perhaps a rightFlatMap
?
void code() {
auto value = f1()
.rightFlatMap([](const struct_a& v){
return f2();
})
.rightMap([](const struct_b& v){
return 5;
})
.leftMap([](const auto& my_error){
return 6;
}).join();
// value should be either 5 or 6
}
rightFlatMap
would have a signature like:
Either<L, R> -> R -> Either<L, X> -> Either<L, X>
yep, something like that (I'm not too familiar with Haskel)
sounds like a good idea.
We probably can probably infer the return type and make leftMap
do leftFlatMap
depending on the type.
Also, I'm not sure that it is related here, but it would be nice to have movable signature, i.e.
rightFlatMap([](struct_a&& v){
...;
}
@
Hey, sorry I was busy with other stuff.
But it seems my example still does not work:
#include <neither/either.hpp>
#include <string>
struct my_error_t {
std::string s;
};
struct struct_a {
int v;
};
struct struct_b {
double v;
};
neither::Either<my_error_t, struct_a> f1();
neither::Either<my_error_t, struct_b> f2();
void code() {
auto e = f1();
e.rightFlatMap([](const auto& v){
});
}
clang++ -c -I/home/basiliscos/development/binary.com/mt5-binary/libs/ -std=c++14 n.cpp
n.cpp:22:7: error: no matching member function for call to 'rightFlatMap'
e.rightFlatMap([](const auto& v){
~~^~~~~~~~~~~~
/home/basiliscos/development/binary.com/mt5-binary/libs/neither/either.hpp:173:18: note: candidate template ignored: substitution failure [with RightCase = (lambda at n.cpp:22:20)]: no
matching function for call to 'ensureEitherLeft'
constexpr auto rightFlatMap(RightCase const& rightCase) const
^
1 error generated.
Also, note that it would be nice to remove const
from rightFlatMap
, because I'd like to move the value, RightCase const& rightCase
forces to copy right value.
Currently, a mapping function must map to a non-void value. Your Lambda returns a void, hence it fails(PullRequest welcome).
As moves are sideeffects, those are forbidden on l-values as explained in #11.
However they are valid on r-values. This should work:
Either<int, std::string> e = left(1);
e.leftMap([](auto x){
return std::make_unique(x);
}).leftMap([](auto&& x) {
return x;
});
If you really want to move a value out of a named Either variable you have to move:
std::move(e).leftMap([](auto&& x){
return x;
});
//e is now invalid and must not be used
I'll extend the documentation and add some tests for this case
Currently, a mapping function must map to a non-void value. Your Lambda returns a void, hence it fails
I have tried:
e.rightFlatMap([](const auto& v){
return struct_b{};
});
still the same error
struct_b
is not an either
. If you want to map values use rightMap
instead.
The differentiation of rightMap and rightFlatMap is necessary to support nested Eithers in a intuitive way.
Indeed that seems works
about moving
However they are valid on r-values. This should work:
neither::Either<int, std::string> e = neither::left(1);
e.leftMap([](auto x){
return std::make_unique<int>(x);
}).leftMap([](auto&& x) {
return x;
});
This does not compile :
/home/basiliscos/development/binary.com/mt5-binary/libs/neither/either.hpp:21:11: error: call to deleted constructor of 'const std::unique_ptr<int, std::default_delete<int> >'
return {x};
^
...
Gotcha, Eithers constructor doesn't work properly with move-only types. Fixing...
Thank you very much for quick feedback & helpful replies :)
should be fixed in the latest commit
Hi,
I assumed that it should be composable, i.e. something like should work:
To let it compile, I have to write something like :
what is the sense of the library if it is not composable, i.e. forces me to unwrap in the next
right_map
the monadic result of the previousright_map
and duplicate errors handling ?WBR, basiliscos