32 #include <type_traits> 33 #include <boost/variant.hpp> 43 template<
typename L,
typename R>
46 using Either_t = boost::variant<L, R>;
49 enum { LeftVal, RightVal };
51 static_assert (!std::is_same<L, R>::value,
"Types cannot be the same.");
68 template<
typename LPrime,
typename RPrime,
69 typename = std::enable_if_t<std::is_convertible<LPrime, L>::value &&
70 std::is_convertible<RPrime, R>::value>>
83 return This_.which () == LeftVal;
88 return This_.which () == RightVal;
94 throw std::runtime_error {
"Tried accessing Left for a Right Either" };
95 return boost::get<L> (This_);
101 throw std::runtime_error {
"Tried accessing Right for a Left Either" };
102 return boost::get<R> (This_);
132 template<
typename RNew>
150 template<
typename RNew>
158 return [] (
const auto& other)
160 static_assert (std::is_convertible<std::decay_t<decltype (other.GetLeft ())>, L>::value,
161 "Other's Either's Left type is not convertible to this Left type.");
162 return other.IsLeft () ?
170 return e1.This_ == e2.This_;
179 template<
typename L,
typename R,
typename F,
typename = std::result_of_t<F ()>>
187 template<
typename L,
typename R>
195 template<
template<
typename>
class Cont,
typename L,
typename R>
198 std::pair<Cont<L>, Cont<R>> result;
199 for (
const auto& either : eithers)
200 if (either.IsLeft ())
201 result.first.push_back (either.GetLeft ());
203 result.second.push_back (either.GetRight ());
208 template<
typename Left,
typename Right,
typename... Args>
214 template<
typename L,
typename R>
230 template<
typename L,
typename R>
244 template<
typename RP>
250 template<
typename AV>
256 return R_t::Left (
f.GetLeft ());
259 return R_t::Left (v.GetLeft ());
261 return R_t::Right (
f.GetRight () (v.GetRight ()));
265 template<
typename L,
typename R>
277 return R_t::Left (value.
GetLeft ());
static Either Right(const R &r)
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
const L & GetLeft() const
friend bool operator!=(const Either &e1, const Either &e2)
boost::variant< L, R > AsVariant() const
friend bool operator==(const Either &e1, const Either &e2)
static BindResult_t< F > Bind(const Either< L, R > &value, const F &f)
static Either< L, RP > Pure(const RP &v)
boost::optional< L > MaybeLeft() const
static Either Left(const L &l)
static std::enable_if_t<!std::is_convertible< RNew, R >::value, Either< L, RNew > > Right(const RNew &r)
R RightOr(const Either< L, R > &either, F &&f)
auto Visit(const Either< Left, Right > &either, Args &&... args)
static FmapResult_t< F > Apply(const Either< L, R > &either, const F &f)
std::result_of_t< F(R)> BindResult_t
Either & operator=(const Either &)=default
std::pair< Cont< L >, Cont< R > > PartitionEithers(const Cont< Either< L, R >> &eithers)
static GSLResult_t< Type_t, AV > GSL(const Type_t &f, const AV &v)
typename InstanceApplicative< AF >::template GSLResult< AV >::Type_t GSLResult_t
static auto EmbeddingLeft()
boost::optional< R > MaybeRight() const
static Either< L, RNew > FromMaybe(const boost::optional< RNew > &maybeRight, const L &left)
const R & GetRight() const
The Functor class is used for types that can be mapped over.
Either(const Either< LPrime, RPrime > &other)