Skip to content

Instantly share code, notes, and snippets.

@Shirataki2
Created December 21, 2020 17:15
Show Gist options
  • Save Shirataki2/894ebd54e80c156d37bb83b456377cec to your computer and use it in GitHub Desktop.
Save Shirataki2/894ebd54e80c156d37bb83b456377cec to your computer and use it in GitHub Desktop.
実用性 無になってしまった気がするけど供養
pub mod base {
pub trait Zero: Sized {
fn zero() -> Self;
fn is_zero(&self) -> bool;
}
pub trait One: Sized {
fn one() -> Self;
fn is_one(&self) -> bool;
}
pub trait Inv: Sized {
type Output;
fn inv(&self) -> Self::Output;
}
pub trait Signed: Sized {
fn abs(&self) -> Self;
fn abs_sub(&self, other: &Self) -> Self;
fn is_positive(&self) -> bool;
fn is_negative(&self) -> bool;
}
pub trait Unsigned: Sized {}
pub trait Bounded: Sized {
fn min_value(&self) -> Self;
fn max_value(&self) -> Self;
}
macro_rules! integer_primitives {
($($t: tt)*) => {$(
impl Zero for $t {
fn zero() -> Self { 0 }
fn is_zero(&self) -> bool { self == &0 }
}
impl One for $t {
fn one() -> Self { 1 }
fn is_one(&self) -> bool { self == &1 }
}
impl Bounded for $t {
fn min_value(&self) -> Self { std::$t::MIN }
fn max_value(&self) -> Self { std::$t::MAX }
}
)*};
}
macro_rules! signed_int_primitives {
($($t: tt)*) => {$(
impl Signed for $t {
fn abs(&self) -> Self { if self >= &0 { *self } else { -self } }
fn abs_sub(&self, other: &Self) -> Self { if self >= other { self - other } else { other - self } }
fn is_positive(&self) -> bool { self > &0 }
fn is_negative(&self) -> bool { self < &0 }
}
)*};
}
macro_rules! unsigned_int_primitives {
($($t: tt)*) => {$(
impl Unsigned for $t {}
)*};
}
macro_rules! floating_primitives {
($($t: tt)*) => {$(
impl Zero for $t {
fn zero() -> Self { 0.0 }
fn is_zero(&self) -> bool { self == &0.0 }
}
impl One for $t {
fn one() -> Self { 1.0 }
fn is_one(&self) -> bool { self == &1.0 }
}
impl Signed for $t {
fn abs(&self) -> Self { if self >= &0.0 { *self } else { -self } }
fn abs_sub(&self, other: &Self) -> Self { (self - other).abs() }
fn is_positive(&self) -> bool { self > &0.0 }
fn is_negative(&self) -> bool { self < &0.0 }
}
impl Bounded for $t {
fn min_value(&self) -> Self { std::$t::MIN }
fn max_value(&self) -> Self { std::$t::MAX }
}
)*};
}
integer_primitives!(u128 u64 u32 u16 u8 usize i128 i64 i32 i16 i8 isize);
signed_int_primitives!(i128 i64 i32 i16 i8 isize);
unsigned_int_primitives!(u128 u64 u32 u16 u8 usize);
floating_primitives!(f32 f64);
}
pub mod common {
use std::ops::*;
use super::base;
pub trait Elem: Sized + Copy + Clone + PartialEq {}
impl<T: Sized + Clone + Copy + PartialEq> Elem for T {}
pub trait Magma: Elem + Add<Output=Self> {}
impl<T: Elem + Add<Output=Self>> Magma for T {}
pub trait Associative: Magma {}
impl<T: Magma> Associative for T {}
pub trait SemiGroup: Magma + Associative {}
impl<T: Magma + Associative> SemiGroup for T {}
pub trait Monoid: SemiGroup + base::Zero {}
impl<T: SemiGroup + base::Zero> Monoid for T {}
pub trait ComMonoid: Monoid + AddAssign + PartialOrd {}
impl<T: Monoid + AddAssign + PartialOrd> ComMonoid for T {}
pub trait Group: Monoid + Neg<Output=Self> {}
impl<T: Monoid + Neg<Output=Self>> Group for T {}
pub trait AbelGroup: ComMonoid + Group {}
impl<T: Group + ComMonoid> AbelGroup for T {}
pub trait SemiRing: ComMonoid + Mul<Output=Self> + base::One {}
impl<T: ComMonoid + Mul<Output=Self> + base::One> SemiRing for T {}
pub trait Ring: AbelGroup + SemiRing {}
impl<T: AbelGroup + SemiRing> Ring for T {}
pub trait ComRing: Ring + MulAssign {}
impl<T: Ring + MulAssign> ComRing for T {}
pub trait Field: ComRing + Div<Output=Self> + DivAssign {}
impl<T: ComRing + Div<Output=Self> + DivAssign> Field for T {}
}
#[cfg(test)]
mod tests {
use super::base::*;
use super::common::*;
use std::ops::*;
trait Sum {
type Output;
fn sum(&self) -> Self::Output;
}
#[derive(PartialEq, Copy, Clone)]
struct GCD<T: ComMonoid>(T);
impl<T: ComMonoid> Zero for GCD<T> {
fn zero() -> Self { GCD(T::zero()) }
fn is_zero(&self) -> bool { self.0.is_zero() }
}
impl<T: ComMonoid + Rem<Output=T>> Add for GCD<T> {
type Output = GCD<T>;
fn add(self, rhs: Self) -> Self {
let mut x = self.0.clone();
let mut y = rhs.0.clone();
while y > T::zero() {
let r = x % y;
x = y;
y = r;
}
Self(x)
}
}
struct MonoidList<T: Monoid>(Vec<T>);
impl<T: Monoid> Sum for MonoidList<T> {
type Output = T;
fn sum(&self) -> T {
self.0.iter().fold(T::zero(), |acc, &x| acc + x)
}
}
#[test]
fn test_1() {
let v: MonoidList<GCD<u32>> = MonoidList(vec![GCD(18), GCD(12), GCD(36)]);
assert_eq!(v.sum(), GCD(6));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment