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.");
59 explicit Either (
const L& l)
64 explicit Either (
const R& r)
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>
126 static Either<L, RNew>
FromMaybe (
const std::optional<RNew>& maybeRight,
const L& left)
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>>>
160 return either.IsRight () ?
161 Right (either.GetRight ()) :
165 template<
typename RNew>
166 static std::enable_if_t<!std::is_convertible<RNew, R>::value,
Either<L, RNew>>
Right (
const RNew& r)
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 ()>>
195 R
RightOr (
const Either<L, R>& either, F&&
f)
197 return either.IsRight () ?
202 template<
typename L,
typename R>
205 return either.IsRight () ?
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>
226 return Visit (either.AsVariant (), std::forward<Args> (args)...);
229 template<
typename L,
typename R>
238 if (either.IsLeft ())
245 template<
typename L,
typename R>
254 struct GSLResult<
Either<L, V>>
256 using Type_t =
Either<L, std::result_of_t<R (
const V&)>>;
259 template<
typename RP>
260 static Either<L, RP>
Pure (
const RP& v)
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>
281 struct InstanceMonad<Either<L, R>>
292 return R_t::Left (value.GetLeft ());
294 return f (value.GetRight ());