use crate::traits::functor::Functor;
use crate::traits::pure::Pure;
pub trait Applicative: Functor + Pure {
fn apply<T, B>(&self, value: &Self::Output<T>) -> Self::Output<B>
where
Self::Source: Fn(&T) -> B,
B: 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;
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;
#[inline]
fn sequence_right<A, B>(fa: &Self::Output<A>, fb: &Self::Output<B>) -> Self::Output<B>
where
A: Clone,
B: Clone,
{
Self::lift2(|_, b| b.clone(), fa, fb)
}
#[inline]
fn sequence_left<A, B>(fa: &Self::Output<A>, fb: &Self::Output<B>) -> Self::Output<A>
where
A: Clone,
B: Clone,
{
Self::lift2(|a, _| a.clone(), fa, fb)
}
#[inline]
fn ap2<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::lift2(f, fa, fb)
}
fn apply_owned<T, B>(self, value: Self::Output<T>) -> Self::Output<B>
where
Self::Source: Fn(T) -> B,
T: Clone,
B: Clone;
fn lift2_owned<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;
fn lift3_owned<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;
#[inline]
fn sequence_right_owned<A, B>(fa: Self::Output<A>, fb: Self::Output<B>) -> Self::Output<B>
where
A: Clone,
B: Clone,
{
Self::lift2_owned(|_, b| b, fa, fb)
}
#[inline]
fn sequence_left_owned<A, B>(fa: Self::Output<A>, fb: Self::Output<B>) -> Self::Output<A>
where
A: Clone,
B: Clone,
{
Self::lift2_owned(|a, _| a, fa, fb)
}
}
impl<A> Applicative for Option<A> {
#[inline]
fn apply<T, B>(&self, value: &Self::Output<T>) -> Self::Output<B>
where
Self::Source: Fn(&T) -> B,
B: Clone,
{
match (self, value) {
(Some(func), Some(a)) => Some(func(a)),
_ => None,
}
}
#[inline]
fn lift2<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) {
(Some(a), Some(b)) => Some(f(a, b)),
_ => None,
}
}
#[inline]
fn lift3<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) {
(Some(a), Some(b), Some(c)) => Some(f(a, b, c)),
_ => None,
}
}
#[inline]
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) {
(Some(func), Some(a)) => Some(func(a)),
_ => None,
}
}
#[inline]
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) {
(Some(a), Some(b)) => Some(f(a, b)),
_ => None,
}
}
#[inline]
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) {
(Some(a), Some(b), Some(c)) => Some(f(a, b, c)),
_ => None,
}
}
}
impl<A: Clone, E: std::fmt::Debug + Clone> Applicative for Result<A, E> {
#[inline]
fn apply<T, B>(&self, value: &Self::Output<T>) -> Self::Output<B>
where
Self::Source: Fn(&T) -> B,
B: Clone,
{
match (self, value) {
(Ok(func), Ok(a)) => Ok(func(a)),
(Err(e), _) => Err(e.clone()),
(_, Err(e)) => Err(e.clone()),
}
}
#[inline]
fn lift2<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) {
(Ok(a), Ok(b)) => Ok(f(a, b)),
(Err(e), _) => Err(e.clone()),
(_, Err(e)) => Err(e.clone()),
}
}
#[inline]
fn lift3<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) {
(Ok(a), Ok(b), Ok(c)) => Ok(f(a, b, c)),
(Err(e), _, _) => Err(e.clone()),
(_, Err(e), _) => Err(e.clone()),
(_, _, Err(e)) => Err(e.clone()),
}
}
#[inline]
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) {
(Ok(func), Ok(a)) => Ok(func(a)),
(Err(e), _) => Err(e),
(_, Err(e)) => Err(e),
}
}
#[inline]
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) {
(Ok(a), Ok(b)) => Ok(f(a, b)),
(Err(e), _) => Err(e),
(_, Err(e)) => Err(e),
}
}
#[inline]
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) {
(Ok(a), Ok(b), Ok(c)) => Ok(f(a, b, c)),
(Err(e), _, _) => Err(e),
(_, Err(e), _) => Err(e),
(_, _, Err(e)) => Err(e),
}
}
}
impl<A: Clone> Applicative for Vec<A> {
#[inline]
fn apply<T, B>(&self, value: &Self::Output<T>) -> Self::Output<B>
where
Self::Source: Fn(&T) -> B,
B: Clone,
{
let mut result = Vec::new();
for func in self {
for val in value {
result.push(func(val));
}
}
result
}
#[inline]
fn lift2<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,
{
let mut result = Vec::with_capacity(fa.len() * fb.len());
for a in fa {
for b in fb {
result.push(f(a, b));
}
}
result
}
#[inline]
fn lift3<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,
{
let mut result = Vec::with_capacity(fa.len() * fb.len() * fc.len());
for ((a, b), c) in fa
.iter()
.flat_map(|a| fb.iter().map(move |b| (a, b)))
.flat_map(|(a, b)| fc.iter().map(move |c| ((a, b), c)))
{
result.push(f(a, b, c));
}
result
}
#[inline]
fn apply_owned<T, B>(self, value: Self::Output<T>) -> Self::Output<B>
where
Self::Source: Fn(T) -> B,
T: Clone,
B: Clone,
{
let mut result = Vec::new();
for func in self {
for val in value.clone() {
result.push(func(val));
}
}
result
}
#[inline]
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,
{
let mut result = Vec::with_capacity(fa.len() * fb.len());
for a in fa {
for b in fb.clone() {
result.push(f(a.clone(), b));
}
}
result
}
#[inline]
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,
{
let mut result = Vec::with_capacity(fa.len() * fb.len() * fc.len());
for a in fa.into_iter() {
for b in fb.clone() {
for c in fc.clone() {
result.push(f(a.clone(), b.clone(), c.clone()));
}
}
}
result
}
}