use crate::traits::monad::Monad;
pub trait MonadError<E>: Monad {
fn throw<T>(error: E) -> Self::Output<T>;
fn catch<F>(&self, f: F) -> Self::Output<Self::Source>
where
F: Fn(&E) -> Self::Output<Self::Source>,
Self::Source: Clone;
fn catch_owned<F>(self, f: F) -> Self::Output<Self::Source>
where
F: Fn(E) -> Self::Output<Self::Source>,
Self::Source: Clone,
Self: Sized;
}
pub trait ErrorMapper<E> {
type Source;
fn map_error_to<NewE, F>(&self, f: F) -> Result<Self::Source, NewE>
where
F: Fn(&E) -> NewE,
Self::Source: Clone;
fn map_error_to_owned<NewE, F>(self, f: F) -> Result<Self::Source, NewE>
where
F: Fn(E) -> NewE,
Self::Source: Clone,
Self: Sized;
}
impl<T: Clone, E: Clone + std::fmt::Debug> MonadError<E> for Result<T, E> {
#[inline]
fn throw<U>(error: E) -> Self::Output<U> {
Err(error)
}
#[inline]
fn catch<F>(&self, f: F) -> Self::Output<Self::Source>
where
F: Fn(&E) -> Self::Output<Self::Source>,
Self::Source: Clone,
{
match self {
Ok(value) => Ok(value.clone()),
Err(error) => f(error),
}
}
#[inline]
fn catch_owned<F>(self, f: F) -> Self::Output<Self::Source>
where
F: Fn(E) -> Self::Output<Self::Source>,
Self::Source: Clone,
Self: Sized,
{
match self {
Ok(value) => Ok(value),
Err(error) => f(error),
}
}
}
impl<T: Clone, E> ErrorMapper<E> for Result<T, E> {
type Source = T;
#[inline]
fn map_error_to<NewE, F>(&self, f: F) -> Result<Self::Source, NewE>
where
F: Fn(&E) -> NewE,
Self::Source: Clone,
{
match self {
Ok(value) => Ok(value.clone()),
Err(error) => Err(f(error)),
}
}
#[inline]
fn map_error_to_owned<NewE, F>(self, f: F) -> Result<Self::Source, NewE>
where
F: Fn(E) -> NewE,
Self::Source: Clone,
Self: Sized,
{
match self {
Ok(value) => Ok(value),
Err(error) => Err(f(error)),
}
}
}
impl<T: Clone> MonadError<()> for Option<T> {
#[inline]
fn throw<U>(_error: ()) -> Self::Output<U> {
None
}
#[inline]
fn catch<F>(&self, f: F) -> Self::Output<Self::Source>
where
F: Fn(&()) -> Self::Output<Self::Source>,
Self::Source: Clone,
{
match self {
Some(value) => Some(value.clone()),
None => f(&()),
}
}
#[inline]
fn catch_owned<F>(self, f: F) -> Self::Output<Self::Source>
where
F: Fn(()) -> Self::Output<Self::Source>,
Self::Source: Clone,
Self: Sized,
{
match self {
Some(value) => Some(value),
None => f(()),
}
}
}
impl<T: Clone> ErrorMapper<()> for Option<T> {
type Source = T;
#[inline]
fn map_error_to<NewE, F>(&self, f: F) -> Result<Self::Source, NewE>
where
F: Fn(&()) -> NewE,
Self::Source: Clone,
{
match self {
Some(value) => Ok(value.clone()),
None => Err(f(&())),
}
}
#[inline]
fn map_error_to_owned<NewE, F>(self, f: F) -> Result<Self::Source, NewE>
where
F: Fn(()) -> NewE,
Self::Source: Clone,
Self: Sized,
{
match self {
Some(value) => Ok(value),
None => Err(f(())),
}
}
}