functional 0.0.7

Functional traits

/// Performance of that operation on members of the set always Muluces a member of the same set
pub trait Closure<T> {
    fn apply(lhs: T, rhs: T) -> T;
}

/// Declare operation as associative
/// Therefore `apply(x, apply(y, z)) == apply(apply(x, y), z`
/// must be true for all `x`, `y` and `z`
pub unsafe trait Associativity<T>: Closure<T> {}


/// This trait may be implemented for operation which can be inverted
/// Like multiplication can be inverted by devision
/// or addition with substraction
pub unsafe trait Devisiablility<T>: Closure<T> {
    /// `devide(apply(x, y), y) == x` and\
    /// `apply(devide(x, y), y) == x` true for all x and y
    fn devide(lhs: T, rhs: T) -> T;
}


/// Operation over set with neutrality element can implement this trait
pub unsafe trait Identity<T>: Closure<T> {
    /// `apply(x, identity()) == x` true for all x
    fn identity() -> T;
}

/// Operations over sets where for each element can be found an inverse element
/// This trait is implemented if operation have neutral element and can be inverted
pub unsafe trait Invertibility<T>: Closure<T> {
    /// Acquire inverse for specified value
    /// `Op::apply(Op::apply(x, y), Op::inverse(y)) == x` must be true for all x and y
    fn inverse(value: T) -> T;
}

unsafe impl<T, Op> Invertibility<T> for Op
    where Op: Devisiablility<T> + Identity<T>
{
    fn inverse(value: T) -> T {
        Self::devide(Self::identity(), value)
    }
}

/// A binary operation is commutative if changing the order\
/// of the operands does not change the result
/// `apply(x, y) == apply(y, x)` is true for all x and y
pub unsafe trait Commutativity<T>: Closure<T> {}




/// A magma is a basic kind of algebraic structure.
/// Specifically, a magma consists of a set, M, equipped with\
/// a single binary operation, M × M → M.
/// The binary operation must be closed by definition but no other properties are imposed.
pub trait Magma
    where Self: Sized
{
    type Operation: Closure<Self>;
    fn apply(lhs: Self, rhs: Self) -> Self {
        Self::Operation::apply(lhs, rhs)
    }
}


/// A semigroup is an algebraic structure consisting of\
/// a set together with an associative binary operation.
/// The binary operation of a semigroup is most often denoted multiplicatively:\
/// x·y, or simply xy, denotes the result of applying\
/// the semigroup operation to the ordered pair (x, y).
pub trait Semigroup: Magma {}
impl<T, Op> Semigroup for T
    where T: Magma<Operation = Op>,
          Op: Associativity<T>
{
}


/// A monoid is an algebraic structure with\
/// a single associative binary operation and an identity element.
pub trait Monoid: Magma {
    fn mempty() -> Self;
    fn mappend(self, rhs: Self) -> Self;
}
impl<T, Op> Monoid for T
    where T: Magma<Operation = Op>,
          Op: Associativity<T> + Identity<T>
{
    fn mempty() -> Self {
        Op::identity()
    }
    fn mappend(self, rhs: Self) -> Self {
        Op::apply(self, rhs)
    }
}



/// A quasigroup is an algebraic structure resembling\
/// a group in the sense that "division" is always possible.\
/// Quasigroups differ from groups mainly in that they need not be associative.
pub trait Quasigroup: Magma {}
impl<T, Op> Quasigroup for T
    where T: Magma<Operation = Op>,
          Op: Devisiablility<T>
{
}


/// A loop is a quasigroup with an identity element
pub trait Loop: Magma {}
impl<T, Op> Loop for T
    where T: Magma<Operation = Op>,
          Op: Devisiablility<T> + Identity<T>
{
}


/// A group is an algebraic structure consisting of
/// a set of elements equipped with an operation\
/// that combines any two elements to form a third element.
/// The operation satisfies four conditions called the group axioms,\
/// namely closure, associativity, identity and invertibility
pub trait Group: Magma {}
impl<T, Op> Group for T
    where T: Magma<Operation = Op>,
          Op: Devisiablility<T> + Associativity<T> + Identity<T>
{
}

/// An abelian group, also called a commutative group,\
/// is a group (`Group`) in which the result of applying\
/// the group operation to two group elements does not depend\
/// on the order in which they are written.
pub trait AbelianGroup: Group {}
impl<T, Op> AbelianGroup for T
    where T: Magma<Operation = Op>,
          Op: Devisiablility<T> + Associativity<T> + Identity<T> + Commutativity<T>
{
}