use crate::prelude::*;
pub trait Functor: HKT {
fn fmap<B, F>(&self, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> B,
B: Clone;
fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
where
F: Fn(Self::Source) -> B,
B: Clone,
Self: Sized;
#[inline]
fn replace<B>(&self, value: &B) -> Self::Output<B>
where
B: Clone,
{
self.fmap(|_| value.clone())
}
#[inline]
fn replace_owned<B>(&self, value: B) -> Self::Output<B>
where
B: Clone,
Self: Sized,
{
self.fmap(|_| value.clone())
}
#[inline]
fn void(&self) -> Self::Output<()> {
self.fmap(|_| ())
}
#[inline]
fn void_owned(self) -> Self::Output<()>
where
Self: Sized,
{
self.fmap_owned(|_| ())
}
}
pub trait FunctorExt: Functor {
#[inline]
fn try_map_or<B, E, F>(&self, default: B, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> Result<B, E>,
B: Clone,
{
self.fmap(|a| match f(a) {
Ok(b) => b,
Err(_) => default.clone(),
})
}
#[inline]
fn try_map_or_else<B, E, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> Result<B, E>,
B: Clone,
D: Fn(&E) -> B,
{
self.fmap(|a| match f(a) {
Ok(b) => b,
Err(e) => default_fn(&e),
})
}
fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> Option<B>;
}
impl<T> Functor for Vec<T> {
#[inline]
fn fmap<B, F>(&self, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> B,
{
self.iter().map(f).collect()
}
#[inline]
fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
where
F: Fn(Self::Source) -> B,
Self: Sized,
{
self.into_iter().map(f).collect()
}
}
impl<T> FunctorExt for Vec<T> {
#[inline]
fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
where
F: FnMut(&Self::Source) -> Option<B>,
{
self.iter().filter_map(f).collect()
}
#[inline]
fn try_map_or<B, E, F>(&self, default: B, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> Result<B, E>,
B: Clone,
{
self.iter()
.map(|x| match f(x) {
Ok(b) => b,
Err(_) => default.clone(),
})
.collect()
}
#[inline]
fn try_map_or_else<B, E, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> Result<B, E>,
D: Fn(&E) -> B,
{
self.iter()
.map(|x| match f(x) {
Ok(b) => b,
Err(e) => default_fn(&e),
})
.collect()
}
}
impl<T> FunctorExt for Option<T> {
#[inline]
fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
where
F: FnOnce(&Self::Source) -> Option<B>,
{
self.as_ref().and_then(f)
}
#[inline]
fn try_map_or<B, E, F>(&self, default: B, f: F) -> Self::Output<B>
where
F: FnOnce(&Self::Source) -> Result<B, E>,
B: Clone,
{
match self {
Some(value) => match f(value) {
Ok(b) => Some(b),
Err(_) => Some(default.clone()),
},
None => None,
}
}
#[inline]
fn try_map_or_else<B, E, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
where
F: FnOnce(&Self::Source) -> Result<B, E>,
D: Fn(&E) -> B,
{
match self {
Some(value) => match f(value) {
Ok(b) => Some(b),
Err(e) => Some(default_fn(&e)),
},
None => None,
}
}
}
impl<T, E: std::fmt::Debug> FunctorExt for Result<T, E>
where
E: Clone + Default,
{
#[inline]
fn filter_map<B, F>(&self, f: F) -> Self::Output<B>
where
F: FnOnce(&Self::Source) -> Option<B>,
{
match self {
Ok(value) => match f(value) {
Some(b) => Ok(b),
None => Err(E::default()),
},
Err(e) => Err(e.clone()),
}
}
#[inline]
fn try_map_or<B, E2, F>(&self, default: B, f: F) -> Self::Output<B>
where
F: FnOnce(&Self::Source) -> Result<B, E2>,
B: Clone,
{
match self {
Ok(value) => match f(value) {
Ok(b) => Ok(b),
Err(_) => Ok(default.clone()),
},
Err(e) => Err(e.clone()),
}
}
#[inline]
fn try_map_or_else<B, E2, D, F>(&self, default_fn: D, f: F) -> Self::Output<B>
where
F: FnOnce(&Self::Source) -> Result<B, E2>,
D: Fn(&E2) -> B,
{
match self {
Ok(value) => match f(value) {
Ok(b) => Ok(b),
Err(e) => Ok(default_fn(&e)),
},
Err(e) => Err(e.clone()),
}
}
}
impl<T> Functor for Option<T> {
#[inline]
fn fmap<B, F>(&self, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> B,
B: Clone,
{
self.as_ref().map(f)
}
#[inline]
fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
where
F: Fn(Self::Source) -> B,
Self: Sized,
{
self.map(f)
}
}
impl<A, E: std::fmt::Debug + Clone> Functor for Result<A, E> {
#[inline]
fn fmap<B, F>(&self, f: F) -> Self::Output<B>
where
F: Fn(&Self::Source) -> B,
B: Clone,
{
match self {
Ok(value) => Ok(f(value)),
Err(e) => Err(e.clone()),
}
}
#[inline]
fn fmap_owned<B, F>(self, f: F) -> Self::Output<B>
where
F: Fn(Self::Source) -> B,
Self: Sized,
{
match self {
Ok(value) => Ok(f(value)),
Err(e) => Err(e.clone()),
}
}
}