lubeck 0.0.0-prealpha.5-abandoned

Functional programming framework written in cutting edge rust
Documentation
use std::ops::{Add, Mul};

use super::Monoid;

/// One short general note here:
///
/// The implementations of some of the methods in this trait are not optimal performance wise!
pub trait Foldable<A> {
    fn foldr<F, B>(self, folder: F, init: B) -> B
    where
        F: Fn(B, A) -> B;

    fn fold_map<F, M>(self, f: F) -> M
    where
        Self: Sized,
        F: Fn(A) -> M,
        M: Monoid,
    {
        self.foldr(|m_res, a| m_res.mappend(f(a)), M::mempty())
    }

    fn fold1<F>(self, folder: F) -> Option<A>
    where
        Self: Sized,
        F: Fn(A, A) -> A,
    {
        self.foldr(
            |a_res, a| {
                if let Some(r) = a_res {
                    Some(folder(a, r))
                } else {
                    Some(a)
                }
            },
            None,
        )
    }

    fn null(self) -> bool
    where
        Self: Sized,
    {
        self.foldr(|_, _| false, true)
    }

    fn to_list(self) -> Vec<A>
    where
        Self: Sized,
    {
        self.foldr(
            |mut v_res, elem| {
                v_res.push(elem);
                v_res
            },
            Vec::new(),
        )
    }

    fn length(self) -> usize
    where
        Self: Sized,
    {
        self.foldr(|len, _| len + 1, 0)
    }
}

pub trait FoldableExtMonoid<M>: Foldable<M> + Sized
where
    M: Monoid,
{
    fn fold(self) -> M {
        self.foldr(|m_res, m| m_res.mappend(m), M::mempty())
    }
}

pub trait FoldableExtEq<A>: Foldable<A> + Sized
where
    A: PartialEq,
{
    fn elem(self, search_for: A) -> bool {
        self.foldr(|b_res, elem| b_res || search_for.eq(&elem), false)
    }
}

pub trait FoldableExtOrd<A>: Foldable<A> + Sized
where
    A: PartialOrd,
{
    fn maximum(self) -> Option<A> {
        self.foldr(
            |prev_max, elem| {
                if let Some(max) = prev_max {
                    Some(if elem > max { elem } else { max })
                } else {
                    Some(elem)
                }
            },
            None,
        )
    }

    fn minimum(self) -> Option<A> {
        self.foldr(
            |prev_min, elem| {
                if let Some(min) = prev_min {
                    Some(if elem < min { elem } else { min })
                } else {
                    Some(elem)
                }
            },
            None,
        )
    }
}

pub trait FoldableExtSum<A>: Foldable<A> + Sized
where
    A: Add<Output = A> + Monoid,
{
    fn sum(self) -> A {
        self.foldr(|sum, a| sum.add(a), A::mempty())
    }
}

pub trait FoldableExtProd<A>: Foldable<A> + Sized
where
    A: Mul<Output = A> + Monoid,
{
    fn sum(self) -> A {
        self.foldr(|sum, a| sum.mul(a), A::mempty())
    }
}