<

Implementing the Either monad in Rust

I've started to really enjoy writing Rust, I think having an advanced enough type system really helps mitigate errors and helps ensure that code is correct. I love Haskell for this exact reason, I truly believe that it helps developers ensure that code is correct.


Out of curiousity, I wanted to know If I could have something like the Either monad in Rust, turns out that I can!. The idea behind this is based off something called Lightweight Higher Kinded Types , I will possibly talk about this sometime later as I expand on this post. Additionally please visit fp-core.rs for more information. It is about 2am right now, so I want to get the code out of the way ASAP.


And here you have it, the Either monad.
pub trait HKT<A, B> {
type URI;
type Target;
}
pub trait Functor<A, B>: HKT<A, B> {
fn fmap<F>(self, f: F) -> <Self as HKT<A, B>>::Target
where F: FnOnce(A) -> B;
}
pub trait Chain<A, B>: HKT<A, B> {
fn chain<F>(self, f: F) -> <Self as HKT<A, B>>::Target
where F: FnOnce(A) -> <Self as HKT<A, B>>::Target;
}
pub trait HKT3<A, B, C> {
type Target2;
}
trait Apply<A, F, B> : Functor<A, B> + HKT3<A, F, B>
where F: FnOnce(A) -> B,
{
fn ap(self, f: <Self as HKT3<A, F, B>>::Target2) ->
<Self as HKT<A, B>>::Target;
}
trait Pure<A>: HKT<A, A> {
fn of(self) -> <Self as HKT<A, A>>::Target;
}

Here is the actual data structure for our Either monad
pub enum Either<L, R> {
Left(L),
Right(R)
}

And now for the implementation
impl<L, R> Either<L, R> {
fn unwrap(self) -> R {
match self {
Either::Left(l) => panic!("left value"),
Either::Right(r) => r
}
}
}
impl <C, A, B> HKT<A, B> for Either<C, A> {
type URI = Self;
type Target = Either<C, B>;
}
impl <C, A, B> Functor<A, B> for Either<C, A> {
fn fmap<F>(self, f: F) -> <Self as HKT<A, B>>::Target
where F: FnOnce(A) -> B {
match self {
Either::Left(x) => Either::Left(x),
Either::Right(x) => Either::Right(f(x))
}
}
}
impl<C, A, B> Chain<A, B> for Either<C, A> {
fn chain<F>(self, f: F) -> Self::Target
where F: FnOnce(A) -> <Self as HKT<A, B>>::Target {
match self {
Either::Left(x) => Either::Left(x),
Either::Right(x) => f(x)
}
}
}
impl <D, A, B, C> HKT3<A, B, C> for Either<D, A> {
type Target2 = Either<D, B>;
}
impl<C, A, F, B> Apply<A, F, B> for Either<C, A>
where F: FnOnce(A) -> B,
{
fn ap(self, f: Self::Target2) -> Self::Target {
match self {
Either::Left(l) => Either::Left(l),
Either::Right(r) => f.fmap(|z| z(r))
}
}
}