use std::ops::Rem;
use crate::{
algebraic_structure::operation::{Max, Min, GCD},
utils::num_traits::{Bounded, Zero},
};
pub trait Semilattice {
type Val: Clone;
fn id() -> Self::Val;
fn op(x: &Self::Val, y: &Self::Val) -> Self::Val;
}
impl<T: Ord + Bounded + Clone> Semilattice for Min<T> {
type Val = T;
fn id() -> Self::Val {
T::max_value()
}
fn op(x: &Self::Val, y: &Self::Val) -> Self::Val {
x.min(y).clone()
}
}
impl<T: Ord + Bounded + Clone> Semilattice for Max<T> {
type Val = T;
fn id() -> Self::Val {
T::max_value()
}
fn op(x: &Self::Val, y: &Self::Val) -> Self::Val {
x.max(y).clone()
}
}
impl<T: Zero + Rem<T>> Semilattice for GCD<T> {
type Val = usize;
fn id() -> Self::Val {
0
}
fn op(x: &Self::Val, y: &Self::Val) -> Self::Val {
GCD::gcd(x, y)
}
}