34 #include <type_traits> 44 template<
typename L,
typename R>
47 using Either_t = std::variant<L, R>;
50 enum { LeftVal, RightVal };
52 static_assert (!std::is_same<L, R>::value,
"Types cannot be the same.");
76 return This_.index () == LeftVal;
81 return This_.index () == RightVal;
87 throw std::runtime_error {
"Tried accessing Left for a Right Either" };
88 return std::get<L> (This_);
94 throw std::runtime_error {
"Tried accessing Right for a Left Either" };
95 return std::get<R> (This_);
125 template<
typename RNew>
143 template<
typename... Vars>
146 return Either { std::visit ([] (
auto&& arg) {
return L { std::forward<decltype (arg)> (arg) }; }, var) };
149 template<
typename... Vars>
153 Right (either.GetRight ()) :
157 template<
typename LPrime,
typename = std::enable_if_t<std::is_convertible_v<LPrime, L>>>
165 template<
typename RNew>
173 return [] (
const auto& other)
175 static_assert (std::is_convertible<std::decay_t<decltype (other.GetLeft ())>, L>::value,
176 "Other's Either's Left type is not convertible to this Left type.");
177 return other.IsLeft () ?
185 return e1.This_ == e2.This_;
194 template<
typename L,
typename R,
typename F,
typename = std::result_of_t<F ()>>
202 template<
typename L,
typename R>
210 template<
template<
typename>
class Cont,
typename L,
typename R>
213 std::pair<Cont<L>, Cont<R>> result;
214 for (
const auto& either : eithers)
215 if (either.IsLeft ())
216 result.first.push_back (either.GetLeft ());
218 result.second.push_back (either.GetRight ());
223 template<
typename Left,
typename Right,
typename... Args>
229 template<
typename L,
typename R>
245 template<
typename L,
typename R>
259 template<
typename RP>
265 template<
typename AV>
271 return R_t::Left (
f.GetLeft ());
274 return R_t::Left (v.GetLeft ());
276 return R_t::Right (
f.GetRight () (v.GetRight ()));
280 template<
typename L,
typename R>
292 return R_t::Left (value.
GetLeft ());
static Either LeftLift(const Either< std::variant< Vars... >, R > &either)
auto Visit(const Either< Left, Right > &either, Args &&... args)
static Either Left(const L &l)
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
const L & GetLeft() const
const R & GetRight() const
The Functor class is used for types that can be mapped over.
static FmapResult_t< F > Apply(const Either< L, R > &either, const F &f)
Either & operator=(const Either &)=default
static Either LeftLift(const std::variant< Vars... > &var)
static Either LeftLift(const Either< LPrime, R > &either)
static GSLResult_t< Type_t, AV > GSL(const Type_t &f, const AV &v)
std::variant< L, R > AsVariant() const
static Either< L, RNew > FromMaybe(const std::optional< RNew > &maybeRight, const L &left)
typename InstanceApplicative< AF >::template GSLResult< AV >::Type_t GSLResult_t
std::pair< Cont< L >, Cont< R > > PartitionEithers(const Cont< Either< L, R >> &eithers)
static BindResult_t< F > Bind(const Either< L, R > &value, const F &f)
friend bool operator!=(const Either &e1, const Either &e2)
static std::enable_if_t<!std::is_convertible< RNew, R >::value, Either< L, RNew > > Right(const RNew &r)
static auto EmbeddingLeft()
std::optional< L > MaybeLeft() const
static Either Right(const R &r)
static Either< L, RP > Pure(const RP &v)
std::optional< R > MaybeRight() const
std::result_of_t< F(R)> BindResult_t
friend bool operator==(const Either &e1, const Either &e2)
R RightOr(const Either< L, R > &either, F &&f)