functional 0.0.7

Functional traits

use std::{ops, num, iter};
use super::groups::*;

/// One of the basic binary operation type
/// It's autoimplemeted for all types which implement ops::Add<Self, Output=Self>
pub struct Add;
impl<T> Closure<T> for Add
    where T: ops::Add<Output = T>
{
    fn apply(lhs: T, rhs: T) -> T {
        lhs + rhs
    }
}

unsafe impl Associativity<isize> for Add {}
unsafe impl Associativity<i8> for Add {}
unsafe impl Associativity<i16> for Add {}
unsafe impl Associativity<i32> for Add {}
unsafe impl Associativity<i64> for Add {}
unsafe impl Associativity<usize> for Add {}
unsafe impl Associativity<u8> for Add {}
unsafe impl Associativity<u16> for Add {}
unsafe impl Associativity<u32> for Add {}
unsafe impl Associativity<u64> for Add {}
unsafe impl Associativity<f32> for Add {}
unsafe impl Associativity<f64> for Add {}
unsafe impl Commutativity<isize> for Add {}
unsafe impl Commutativity<i8> for Add {}
unsafe impl Commutativity<i16> for Add {}
unsafe impl Commutativity<i32> for Add {}
unsafe impl Commutativity<i64> for Add {}
unsafe impl Commutativity<usize> for Add {}
unsafe impl Commutativity<u8> for Add {}
unsafe impl Commutativity<u16> for Add {}
unsafe impl Commutativity<u32> for Add {}
unsafe impl Commutativity<u64> for Add {}
unsafe impl Commutativity<f32> for Add {}
unsafe impl Commutativity<f64> for Add {}

unsafe impl<T> Identity<T> for Add
    where T: num::Zero + ops::Add<Output = T>
{
    fn identity() -> T {
        <T as num::Zero>::zero()
    }
}



/// Wrapper over type and addition
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct Sum<T>(pub T);
impl<T> ops::Add for Sum<T>
    where T: ops::Add<Output = T>
{
    type Output = Sum<T>;
    fn add(self, rhs: Self) -> Self {
        Sum(self.0.add(rhs.0))
    }
}

unsafe impl<T> Associativity<Sum<T>> for Add
    where Add: Associativity<T>,
          T: ops::Add<Output = T>
{
}


unsafe impl<T> Identity<Sum<T>> for Add
    where Add: Identity<T>,
          T: ops::Add<Output = T>
{
    fn identity() -> Sum<T> {
        Sum(Self::identity())
    }
}

impl<T> Magma for Sum<T>
    where T: ops::Add<Output = T>
{
    type Operation = Add;
}




/// One of the basic binary operation type
/// It's autoimplemeted for all types which implement ops::Mul<Self, Output=Self>
pub struct Mul;
impl<T> Closure<T> for Mul
    where T: ops::Mul<Output = T>
{
    fn apply(lhs: T, rhs: T) -> T {
        lhs * rhs
    }
}

unsafe impl Associativity<isize> for Mul {}
unsafe impl Associativity<i8> for Mul {}
unsafe impl Associativity<i16> for Mul {}
unsafe impl Associativity<i32> for Mul {}
unsafe impl Associativity<i64> for Mul {}
unsafe impl Associativity<usize> for Mul {}
unsafe impl Associativity<u8> for Mul {}
unsafe impl Associativity<u16> for Mul {}
unsafe impl Associativity<u32> for Mul {}
unsafe impl Associativity<u64> for Mul {}
unsafe impl Associativity<f32> for Mul {}
unsafe impl Associativity<f64> for Mul {}
unsafe impl Commutativity<isize> for Mul {}
unsafe impl Commutativity<i8> for Mul {}
unsafe impl Commutativity<i16> for Mul {}
unsafe impl Commutativity<i32> for Mul {}
unsafe impl Commutativity<i64> for Mul {}
unsafe impl Commutativity<usize> for Mul {}
unsafe impl Commutativity<u8> for Mul {}
unsafe impl Commutativity<u16> for Mul {}
unsafe impl Commutativity<u32> for Mul {}
unsafe impl Commutativity<u64> for Mul {}
unsafe impl Commutativity<f32> for Mul {}
unsafe impl Commutativity<f64> for Mul {}

unsafe impl<T> Identity<T> for Mul
    where T: num::One + ops::Mul<Output = T>
{
    fn identity() -> T {
        <T as num::One>::one()
    }
}



/// Wrapper over type and multiplication
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct Prod<T>(pub T);
impl<T> ops::Mul for Prod<T>
    where T: ops::Mul<Output = T>
{
    type Output = Prod<T>;
    fn mul(self, rhs: Self) -> Self {
        Prod(self.0.mul(rhs.0))
    }
}

unsafe impl<T> Associativity<Prod<T>> for Mul
    where Mul: Associativity<T>,
          T: ops::Mul<Output = T>
{
}

unsafe impl<T> Identity<Prod<T>> for Mul
    where Mul: Identity<T>,
          T: ops::Mul<Output = T>
{
    fn identity() -> Prod<T> {
        Prod(Self::identity())
    }
}

impl<T> Magma for Prod<T>
    where T: ops::Mul<Output = T>
{
    type Operation = Mul;
}





/// Concatenation operation for sequenses
pub struct Concat;
impl<U, T> Closure<T> for Concat
    where T: iter::IntoIterator<Item = U> + iter::FromIterator<U>
{
    fn apply(lhs: T, rhs: T) -> T {
        lhs.into_iter().chain(rhs.into_iter()).collect()
    }
}

unsafe impl<U, T> Associativity<T> for Concat
    where T: iter::IntoIterator<Item = U> + iter::FromIterator<U>
{
}

unsafe impl<U, T> Identity<T> for Concat
    where T: iter::IntoIterator<Item = U> + iter::FromIterator<U>
{
    fn identity() -> T {
        T::from_iter(iter::empty())
    }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct Sequence<T>(pub T);

impl<U, T> Closure<Sequence<T>> for Concat
    where T: iter::IntoIterator<Item = U> + iter::FromIterator<U>
{
    fn apply(lhs: Sequence<T>, rhs: Sequence<T>) -> Sequence<T> {
        let (Sequence(lhs), Sequence(rhs)) = (lhs, rhs);
        Sequence(lhs.into_iter().chain(rhs.into_iter()).collect())
    }
}

unsafe impl<U, T> Associativity<Sequence<T>> for Concat
    where T: iter::IntoIterator<Item = U> + iter::FromIterator<U>
{
}
unsafe impl<U, T> Identity<Sequence<T>> for Concat
    where T: iter::IntoIterator<Item = U> + iter::FromIterator<U>
{
    fn identity() -> Sequence<T> {
        Sequence(iter::empty().collect())
    }
}

impl<T, Y> Magma for Sequence<T>
    where T: iter::IntoIterator<Item = Y> + iter::FromIterator<Y>
{
    type Operation = Concat;
}