use hkt::*;
use super::applicative::Applicative;
pub trait Monad: Applicative {
fn bind<U, F>(self, f: F) -> rebind1!(Self, U)
where Self::Unit: Rebind1<U>,
generic1!(Self): Sized,
F: Fn(generic1!(Self)) -> rebind1!(Self, U);
fn join<U>(self) -> rebind1!(Self, U)
where Self: Sized,
Self: Generic1,
Self::Unit: Rebind1<U>,
generic1!(Self): Same<Type=rebind1!(Self, U)> + Sized,
generic1!(Self): Generic1<Unit=Self::Unit>;
}
impl<T> Monad for Option<T> {
fn bind<U, F>(self, f: F) -> rebind1!(Self, U)
where F: Fn(T) -> Option<U>
{
match self {
Some(x) => f(x),
None => None
}
}
fn join<U>(self) -> rebind1!(Self, U)
where generic1!(Self): Same<Type=rebind1!(Self, U)>
{
match self {
Some(x) => x.same_cast(),
None => None
}
}
}
impl<T, E> Monad for Result<T, E> {
fn bind<U, F>(self, f: F) -> rebind1!(Self, U)
where F: Fn(T) -> Result<U, E>
{
match self {
Ok(x) => f(x),
Err(err) => Err(err)
}
}
fn join<U>(self) -> rebind1!(Self, U)
where generic1!(Self): Same<Type=rebind1!(Self, U)>
{
match self {
Ok(x) => x.same_cast(),
Err(err) => Err(err)
}
}
}
impl<T> Monad for Vec<T> where T: Clone {
fn bind<U, F>(self, f: F) -> rebind1!(Self, U)
where F: Fn(T) -> Vec<U>
{
self.into_iter().flat_map(|x| f(x)).collect()
}
fn join<U>(self) -> rebind1!(Self, U)
where generic1!(Self): Same<Type=rebind1!(Self, U)>
{
self.into_iter().flat_map(|x| x.same_cast()).collect()
}
}