1use core::marker::PhantomData;
2use alloc::{string::String, format};
3
4pub trait NotMonoid {
5 type Unit;
6 type P1;
7 type P2;
8 type Ret;
9
10 fn unit() -> Self::Unit;
11 fn merge(some: Self::P1, other: Self::P2) -> Self::Ret;
12}
13
14macro_rules! impl_str_not_monoid {
15 ($($id:ident, $ex:expr);* $(;)?) => {$(
16 pub struct $id<'a>(PhantomData<&'a ()>);
17
18 impl<'a> NotMonoid for $id<'a> {
19 type Unit = &'a str;
22 type P1 = Self::Unit;
23 type P2 = Self::P1;
24 type Ret = String;
25
26 fn unit() -> Self::Unit { $ex }
27
28 fn merge(some: Self::P1, other: Self::P2) -> Self::Ret {
29 format!("{}{}{}", some, Self::unit(), other)
30 }
31 }
32 )*};
33}
34
35impl_str_not_monoid! { StrEmpty, "";
36 StrDot, "."; StrSlash, "/";
37 StrAdd, "+"; StrPercent, "%";
38 StrSub, "-"; StrBackslash, "\\";
39 StrMul, "*"; StrUnderscore, "_";
40}
41
42macro_rules! impl_num_not_monoid {
43 ($($ty:ty, $id:ident, $ex:expr);* $(;)?) => {$(
44 pub struct $id;
45
46 impl NotMonoid for $id {
47 type Unit = u8;
48 type P1 = $ty;
50 type P2 = Self::P1;
51 type Ret = Self::P2;
52
53 fn unit() -> Self::Unit { $ex }
54
55 fn merge(some: Self::P1, other: Self::P2) -> Self::Ret {
56 match Self::unit() {
57 0 => some + other,
58 1 => some * other,
59 _ => panic!("Unsupport Unit")
60 }
61 }
62 }
63 )*};
64}
65
66impl_num_not_monoid! {
67 u8, U8Add, 0; i8, I8Add, 0; u8, U8Mul, 1; i8, I8Mul, 1;
68 u16, U16Add, 0; i16, I16Add, 0; u16, U16Mul, 1; i16, I16Mul, 1;
69 u32, U32Add, 0; i32, I32Add, 0; f32, F32Add, 0; u32, U32Mul, 1; i32, I32Mul, 1; f32, F32Mul, 1;
70 u64, U64Add, 0; i64, I64Add, 0; f64, F64Add, 0; u64, U64Mul, 1; i64, I64Mul, 1; f64, F64Mul, 1;
71 usize, UsizeAdd, 0; isize, IsizeAdd, 0; usize, UsizeMul, 1; isize, IsizeMul, 1;
72 u128, U128Add, 0; i128, I128Add, 0; u128, U128Mul, 1; i128, I128Mul, 1;
73}
74
75#[cfg(test)]
76mod test {
77 use crate::assert_eqs;
78 use super::*;
79
80 #[test]
81 fn test_all() {
82 assert_eqs! {
83 "a.b", StrDot::merge("a", "b");
84 5, U8Add::merge(2, 3);
85 6, U8Mul::merge(2, 3);
86 4.6, F64Add::merge(1.2, 3.4);
87 4.08, F64Mul::merge(1.2, 3.4);
88 }
89 }
90}