use crate::Set;
#[cfg(feature = "derive")]
pub use finit_derive::{
Difference, DifferenceAssign, DisjunctiveUnion, DisjunctiveUnionAssign, Intersection,
IntersectionAssign, Union, UnionAssign,
};
pub trait Union<Rhs = Self>: Set {
type Output;
fn union(self, rhs: Rhs) -> Self::Output;
}
pub trait UnionAssign<Rhs = Self>: Set {
fn union_assign(&mut self, rhs: Rhs);
}
pub trait Difference<Rhs = Self>: Set {
type Output;
fn difference(self, rhs: Rhs) -> Self::Output;
}
pub trait DifferenceAssign<Rhs = Self>: Set {
fn difference_assign(&mut self, rhs: Rhs);
}
pub trait Intersection<Rhs = Self>: Set {
type Output;
fn intersection(self, rhs: Rhs) -> Self::Output;
}
pub trait IntersectionAssign<Rhs = Self>: Set {
fn intersection_assign(&mut self, rhs: Rhs);
}
pub trait DisjunctiveUnion<Rhs = Self>: Set {
type Output;
fn disjunctive_union(self, rhs: Rhs) -> Self::Output;
}
pub trait DisjunctiveUnionAssign<Rhs = Self>: Set {
fn disjunctive_union_assign(&mut self, rhs: Rhs);
}
pub mod identity {
pub fn intersection_using_double_difference<A, B>(
a: A,
b: B,
) -> <A as super::Difference<<A as super::Difference<B>>::Output>>::Output
where
A: Clone + super::Difference<B> + super::Difference<<A as super::Difference<B>>::Output>,
{
a.clone().difference(a.difference(b))
}
pub fn disjunctive_union_using_difference_and_union<A, B>(
a: A,
b: B,
) -> <<A as super::Difference<B>>::Output as super::Union<<B as super::Difference<A>>::Output>>::Output
where
A: Clone + super::Difference<B>,
B: Clone + super::Difference<A>,
<A as super::Difference<B>>::Output: super::Union<<B as super::Difference<A>>::Output>,
{
super::Union::union(a.clone().difference(b.clone()), b.difference(a))
}
pub fn difference_using_intersection<A, B>(
a: A,
b: B,
) -> <A as super::Difference<<A as super::Intersection<B>>::Output>>::Output
where
A: Clone
+ super::Intersection<B>
+ super::Difference<<A as super::Intersection<B>>::Output>,
{
a.clone().difference(a.intersection(b))
}
pub fn disjunctive_union_using_union_intersection_and_difference<A, B>(
a: A,
b: B,
) -> <<A as super::Union<B>>::Output as super::Difference<
<A as super::Intersection<B>>::Output,
>>::Output
where
A: Clone + super::Union<B> + super::Intersection<B>,
B: Clone,
<A as super::Union<B>>::Output: super::Difference<<A as super::Intersection<B>>::Output>,
{
super::Difference::difference(a.clone().union(b.clone()), a.intersection(b))
}
}