use crate::datatypes::error::EitherError;
use crate::traits::alternative::Alternative;
use crate::traits::applicative::Applicative;
use crate::traits::bifunctor::Bifunctor;
use crate::traits::functor::Functor;
use crate::traits::hkt::{BinaryHKT, HKT};
use crate::traits::monad::Monad;
use crate::traits::pure::Pure;
use quickcheck::{Arbitrary, Gen};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Either<L, R> {
Left(L),
Right(R),
}
impl<L, R> Either<L, R> {
#[inline]
pub const fn left(l: L) -> Self {
Either::Left(l)
}
#[inline]
pub const fn right(r: R) -> Self {
Either::Right(r)
}
#[inline]
pub const fn is_left(&self) -> bool {
matches!(self, Either::Left(_))
}
#[inline]
pub const fn is_right(&self) -> bool {
matches!(self, Either::Right(_))
}
#[inline]
pub fn fmap_left<T, F>(self, f: F) -> Either<T, R>
where
F: Fn(L) -> T,
{
match self {
Either::Left(l) => Either::Left(f(l)),
Either::Right(r) => Either::Right(r),
}
}
#[inline]
pub fn fmap_right<T, F>(self, mut f: F) -> Either<L, T>
where
F: FnMut(R) -> T,
{
match self {
Either::Left(l) => Either::Left(l),
Either::Right(r) => Either::Right(f(r)),
}
}
#[inline]
pub fn unwrap_left(self) -> L {
match self {
Either::Left(l) => l,
Either::Right(_) => panic!("called unwrap_left on Right value"),
}
}
#[inline]
pub fn unwrap_right(self) -> R {
match self {
Either::Right(r) => r,
Either::Left(_) => panic!("called unwrap_right on Left value"),
}
}
#[inline]
pub fn unwrap(self) -> R {
match self {
Either::Right(r) => r,
Either::Left(_) => panic!("called `Either::unwrap()` on a `Left` value"),
}
}
#[inline]
pub fn unwrap_or(self, default: R) -> R {
match self {
Either::Right(r) => r,
Either::Left(_) => default,
}
}
#[inline]
pub fn left_value(self) -> L
where
Self: Sized,
{
match self {
Either::Left(l) => l,
Either::Right(_) => panic!("called left_value on Right value"),
}
}
#[inline]
pub fn right_value(self) -> R {
match self {
Either::Right(r) => r,
Either::Left(_) => panic!("called right_value on Left value"),
}
}
#[inline]
pub fn left_ref(&self) -> &L {
match self {
Either::Left(l) => l,
Either::Right(_) => panic!("Called left_ref on an Either::Right"),
}
}
#[inline]
pub fn right_ref(&self) -> &R {
self.into_iter()
.next()
.expect("Called right_ref() on a Left value")
}
#[inline]
pub fn right_or(self, default: R) -> R {
self.into_iter().next().unwrap_or(default)
}
#[inline]
pub fn left_or(self, default: L) -> L {
match self {
Either::Left(l) => l,
Either::Right(_) => default,
}
}
#[inline]
pub fn right_option(self) -> Option<R> {
self.into_iter().next()
}
#[inline]
pub fn to_result(self) -> Result<R, L> {
crate::error::either_to_result(self)
}
#[inline]
pub fn from_result(result: Result<R, L>) -> Self {
crate::error::result_to_either(result)
}
pub fn left_iter(self) -> EitherLeftIter<L> {
match self {
Either::Left(l) => EitherLeftIter { left: Some(l) },
Either::Right(_) => EitherLeftIter { left: None },
}
}
pub fn left_iter_ref(&self) -> EitherLeftIterRef<'_, L> {
match self {
Either::Left(l) => EitherLeftIterRef { left: Some(l) },
Either::Right(_) => EitherLeftIterRef { left: None },
}
}
pub fn left_iter_mut(&mut self) -> EitherLeftIterMut<'_, L> {
match self {
Either::Left(l) => EitherLeftIterMut { left: Some(l) },
Either::Right(_) => EitherLeftIterMut { left: None },
}
}
pub fn left_option(self) -> Option<L> {
self.left_iter().next()
}
pub fn left_mut(&mut self) -> &mut L {
self.left_iter_mut()
.next()
.expect("Called left_mut() on a Right value")
}
#[inline]
pub fn try_unwrap_left(self) -> Result<L, EitherError> {
match self {
Either::Left(l) => Ok(l),
Either::Right(_) => Err(EitherError::ExpectedLeft),
}
}
#[inline]
pub fn try_unwrap_right(self) -> Result<R, EitherError> {
match self {
Either::Right(r) => Ok(r),
Either::Left(_) => Err(EitherError::ExpectedRight),
}
}
#[inline]
pub fn try_left_ref(&self) -> Result<&L, EitherError> {
match self {
Either::Left(l) => Ok(l),
Either::Right(_) => Err(EitherError::ExpectedLeft),
}
}
#[inline]
pub fn try_right_ref(&self) -> Result<&R, EitherError> {
match self {
Either::Right(r) => Ok(r),
Either::Left(_) => Err(EitherError::ExpectedRight),
}
}
}
pub struct EitherLeftIter<L> {
left: Option<L>,
}
impl<L> Iterator for EitherLeftIter<L> {
type Item = L;
fn next(&mut self) -> Option<L> {
self.left.take()
}
}
pub struct EitherLeftIterRef<'a, L> {
left: Option<&'a L>,
}
impl<'a, L> Iterator for EitherLeftIterRef<'a, L> {
type Item = &'a L;
fn next(&mut self) -> Option<&'a L> {
self.left.take()
}
}
pub struct EitherLeftIterMut<'a, L> {
left: Option<&'a mut L>,
}
impl<'a, L> Iterator for EitherLeftIterMut<'a, L> {
type Item = &'a mut L;
fn next(&mut self) -> Option<&'a mut L> {
self.left.take()
}
}
impl<L, R> HKT for Either<L, R> {
type Source = R;
type Output<T> = Either<L, T>;
}
impl<L: Clone, R: Clone> Functor for Either<L, R> {
#[inline]
fn fmap<B, F>(&self, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> B,
{
match self {
Either::Left(l) => Either::Left(l.clone()),
Either::Right(r) => Either::Right(f(r)),
}
}
#[inline]
fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
where
F: Fn(Self::Source) -> B,
{
match self {
Either::Left(l) => Either::Left(l),
Either::Right(r) => Either::Right(f(r)),
}
}
}
impl<L, R> Pure for Either<L, R> {
#[inline]
fn pure<T: Clone>(value: &T) -> Self::Output<T> {
Either::Right(value.clone())
}
}
impl<L: Clone, R: Clone> Applicative for Either<L, R> {
fn apply<A, B>(&self, value: &Self::Output<A>) -> Self::Output<B>
where
Self::Source: Fn(&A) -> B,
{
match (self, value) {
(Either::Right(func), Either::Right(a)) => Either::Right(func(a)),
(Either::Left(l), _) => Either::Left(l.clone()),
(_, Either::Left(l)) => Either::Left(l.clone()),
}
}
fn lift2<A, B, C, F>(f: F, fa: &Self::Output<A>, fb: &Self::Output<B>) -> Self::Output<C>
where
F: Fn(&A, &B) -> C,
A: Clone,
B: Clone,
C: Clone,
Self: Sized,
{
match (fa, fb) {
(Either::Right(a), Either::Right(b)) => Either::Right(f(a, b)),
(Either::Left(l), _) => Either::Left(l.clone()),
(_, Either::Left(l)) => Either::Left(l.clone()),
}
}
fn lift3<A, B, C, D, F>(
f: F, fa: &Self::Output<A>, fb: &Self::Output<B>, fc: &Self::Output<C>,
) -> Self::Output<D>
where
F: Fn(&A, &B, &C) -> D,
A: Clone,
B: Clone,
C: Clone,
D: Clone,
Self: Sized,
{
match (fa, fb, fc) {
(Either::Right(a), Either::Right(b), Either::Right(c)) => Either::Right(f(a, b, c)),
(Either::Left(l), _, _) => Either::Left(l.clone()),
(_, Either::Left(l), _) => Either::Left(l.clone()),
(_, _, Either::Left(l)) => Either::Left(l.clone()),
}
}
fn apply_owned<T, B>(self, value: Self::Output<T>) -> Self::Output<B>
where
Self::Source: Fn(T) -> B,
T: Clone,
B: Clone,
{
match (self, value) {
(Either::Right(f), Either::Right(x)) => Either::Right(f(x)),
(Either::Left(l), _) => Either::Left(l),
(_, Either::Left(l)) => Either::Left(l),
}
}
fn lift2_owned<T, U, V, F>(f: F, fa: Self::Output<T>, fb: Self::Output<U>) -> Self::Output<V>
where
F: Fn(T, U) -> V,
T: Clone,
U: Clone,
V: Clone,
Self: Sized,
{
match (fa, fb) {
(Either::Right(x), Either::Right(y)) => Either::Right(f(x, y)),
(Either::Left(l), _) => Either::Left(l),
(_, Either::Left(l)) => Either::Left(l),
}
}
fn lift3_owned<T, U, V, Q, F>(
f: F, fa: Self::Output<T>, fb: Self::Output<U>, fc: Self::Output<V>,
) -> Self::Output<Q>
where
F: Fn(T, U, V) -> Q,
T: Clone,
U: Clone,
V: Clone,
Q: Clone,
Self: Sized,
{
match (fa, fb, fc) {
(Either::Right(x), Either::Right(y), Either::Right(z)) => Either::Right(f(x, y, z)),
(Either::Left(l), _, _) => Either::Left(l),
(_, Either::Left(l), _) => Either::Left(l),
(_, _, Either::Left(l)) => Either::Left(l),
}
}
}
impl<L: Clone, R: Clone> Monad for Either<L, R> {
#[inline]
fn bind<B, F>(&self, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> Self::Output<B>,
{
match self {
Either::Left(l) => Either::Left(l.clone()),
Either::Right(r) => f(r),
}
}
#[inline]
fn join<B>(&self) -> Self::Output<B>
where
Self::Source: Into<Self::Output<B>>,
{
match self {
Either::Left(l) => Either::Left(l.clone()),
Either::Right(r) => r.clone().into(),
}
}
#[inline]
fn bind_owned<U, F>(self, f: F) -> Self::Output<U>
where
F: FnOnce(Self::Source) -> Self::Output<U>,
Self: Sized,
{
match self {
Either::Left(l) => Either::Left(l),
Either::Right(r) => f(r),
}
}
#[inline]
fn join_owned<U>(self) -> Self::Output<U>
where
Self::Source: Into<Self::Output<U>>,
Self: Sized,
{
match self {
Either::Left(l) => Either::Left(l),
Either::Right(r) => r.into(),
}
}
}
impl<L, R> BinaryHKT for Either<L, R> {
type Source2 = L;
type BinaryOutput<NewR, NewL> = Either<NewL, NewR>;
fn map_second<F, NewL>(&self, f: F) -> Either<NewL, R>
where
F: Fn(&L) -> NewL,
R: Clone,
{
match self {
Either::Left(l) => Either::Left(f(l)),
Either::Right(r) => Either::Right(r.clone()),
}
}
fn map_second_owned<F, NewL>(self, f: F) -> Either<NewL, R>
where
F: Fn(L) -> NewL,
{
match self {
Either::Left(l) => Either::Left(f(l)),
Either::Right(r) => Either::Right(r),
}
}
}
impl<L: Clone, R: Clone> Bifunctor for Either<L, R> {
fn first<C, F>(&self, f: F) -> Self::BinaryOutput<C, Self::Source2>
where
F: Fn(&Self::Source) -> C,
C: Clone,
{
match self {
Either::Left(l) => Either::Left(l.clone()),
Either::Right(r) => Either::Right(f(r)),
}
}
fn second<D, G>(&self, g: G) -> Self::BinaryOutput<Self::Source, D>
where
G: Fn(&Self::Source2) -> D,
D: Clone,
{
match self {
Either::Left(l) => Either::Left(g(l)),
Either::Right(r) => Either::Right(r.clone()),
}
}
fn bimap<C, D, F, G>(&self, f: F, g: G) -> Self::BinaryOutput<C, D>
where
F: Fn(&Self::Source) -> C,
G: Fn(&Self::Source2) -> D,
C: Clone,
D: Clone,
{
match self {
Either::Left(l) => Either::Left(g(l)),
Either::Right(r) => Either::Right(f(r)),
}
}
}
impl<L: Default + Clone, R: Clone> Alternative for Either<L, R> {
#[inline]
fn empty_alt<B>() -> Self::Output<B> {
Either::Left(L::default())
}
#[inline]
fn alt(&self, other: &Self) -> Self {
match self {
Either::Right(_) => self.clone(),
Either::Left(_) => other.clone(),
}
}
fn guard(condition: bool) -> Self::Output<()> {
if condition {
Either::Right(())
} else {
Either::Left(L::default())
}
}
#[inline]
fn many(&self) -> Self::Output<Vec<Self::Source>>
where
Self::Source: Clone,
{
match self {
Either::Right(x) => Either::Right(vec![x.clone()]),
Either::Left(_) => Either::Left(L::default()),
}
}
}
pub struct EitherIter<R> {
inner: Option<R>,
}
impl<L, R> IntoIterator for Either<L, R> {
type Item = R;
type IntoIter = EitherIter<R>;
fn into_iter(self) -> Self::IntoIter {
match self {
Either::Right(r) => EitherIter { inner: Some(r) },
Either::Left(_) => EitherIter { inner: None },
}
}
}
impl<R> Iterator for EitherIter<R> {
type Item = R;
fn next(&mut self) -> Option<R> {
self.inner.take()
}
}
pub struct EitherIterRef<'a, R> {
inner: Option<&'a R>,
}
impl<'a, L, R> IntoIterator for &'a Either<L, R> {
type Item = &'a R;
type IntoIter = EitherIterRef<'a, R>;
fn into_iter(self) -> Self::IntoIter {
match self {
Either::Right(r) => EitherIterRef { inner: Some(r) },
Either::Left(_) => EitherIterRef { inner: None },
}
}
}
impl<'a, R> Iterator for EitherIterRef<'a, R> {
type Item = &'a R;
fn next(&mut self) -> Option<&'a R> {
self.inner.take()
}
}
pub struct EitherIterMut<'a, R> {
inner: Option<&'a mut R>,
}
impl<'a, L, R> IntoIterator for &'a mut Either<L, R> {
type Item = &'a mut R;
type IntoIter = EitherIterMut<'a, R>;
fn into_iter(self) -> Self::IntoIter {
match self {
Either::Right(r) => EitherIterMut { inner: Some(r) },
Either::Left(_) => EitherIterMut { inner: None },
}
}
}
impl<'a, R> Iterator for EitherIterMut<'a, R> {
type Item = &'a mut R;
fn next(&mut self) -> Option<&'a mut R> {
self.inner.take()
}
}
impl<L, R> Arbitrary for Either<L, R>
where
L: Arbitrary,
R: Arbitrary,
{
fn arbitrary(g: &mut Gen) -> Self {
let left = L::arbitrary(g);
let right = R::arbitrary(g);
if bool::arbitrary(g) {
Either::Left(left)
} else {
Either::Right(right)
}
}
}