use std::ops::{Add, Mul};
use ops::{Op, Additive, Multiplicative};
use cmp::ApproxEq;
pub trait MagmaApprox<O: Op>
: Sized
+ PartialEq
+ ApproxEq
+ Clone
{
fn approx(self, Self) -> Self;
fn ap(self, _: O, lhs: Self) -> Self {
self.approx(lhs)
}
}
pub trait Magma<O: Op>
: Eq
+ MagmaApprox<O>
{
fn operate(self, lhs: Self) -> Self {
self.approx(lhs)
}
fn op(self, _: O, lhs: Self) -> Self {
self.operate(lhs)
}
}
impl<T> MagmaApprox<Additive> for T
where T: Add<T, Output=T> + PartialEq + ApproxEq + Clone,
{
fn approx(self, lhs: Self) -> Self {
self + lhs
}
}
impl<T> Magma<Additive> for T
where T: MagmaApprox<Additive> + Eq,
{}
impl<T> MagmaApprox<Multiplicative> for T
where T: Mul<T, Output=T> + PartialEq + ApproxEq + Clone,
{
fn approx(self, lhs: Self) -> Self {
self * lhs
}
}
impl<T> Magma<Multiplicative> for T
where T: MagmaApprox<Multiplicative> + Eq,
{}