1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
//! A class for monoids (types with an associative binary operation that has an identity) with //! various general-purpose instances. use super::semigroup::Semigroup; // =============== // === Monoid ==== // =============== /// Mutable Monoid definition. pub trait Monoid : Default + Semigroup { /// Repeat a value n times. Given that this works on a Monoid it will not fail if you request 0 /// or fewer repetitions. fn times_mut(&mut self, n:usize) { if n == 0 { *self = Default::default() } else { let val = self.clone(); for _ in 0..n-1 { self.concat_mut(&val) } } } fn times(&self, n:usize) -> Self { std::iter::repeat(self).take(n).fold(Default::default(),|l,r| l.concat_ref(r)) } } // === Default Impls === impl<T> Monoid for T where T : Default + Semigroup {} // ============= // === Tests === // ============= #[cfg(test)] mod tests { use super::*; #[test] fn option() { let vec_nop : Vec<usize> = vec![]; let vec_1_2 : Vec<usize> = vec![1,2]; let vec_1_2_times_3 : Vec<usize> = vec![1,2,1,2,1,2]; assert_eq!(vec_1_2.times(0) , vec_nop); assert_eq!(vec_1_2.times(1) , vec_1_2); assert_eq!(vec_1_2.times(3) , vec_1_2_times_3); } } // TODO: Think what to do with this. It would not be needed if tuples implement Iter. Alternatively // we could immplement own tuple type. //trait Foldable { // type Item : Monoid; // fn fold(self) -> Self::Item; //} // // // //macro_rules! replace { // ($a:tt,$b:tt) => {$b}; //} // // //macro_rules! define_foldable_for_tuple { // (0$(,$num:tt)*) => { // impl<T:Monoid> Foldable for (T,$(replace!{$num,T}),*) { // type Item = T; // fn fold(self) -> Self::Item { // self.0$(.concat(self.$num))* // } // } // // impl<T:Monoid> Foldable for &(T,$(replace!{$num,T}),*) { // type Item = T; // fn fold(self) -> Self::Item { // self.0.clone()$(.concat(&self.$num))* // } // } // }; //} // //define_foldable_for_tuple![0]; //define_foldable_for_tuple![0,1]; //define_foldable_for_tuple![0,1,2]; //define_foldable_for_tuple![0,1,2,3]; //define_foldable_for_tuple![0,1,2,3,4]; //define_foldable_for_tuple![0,1,2,3,4,5]; //define_foldable_for_tuple![0,1,2,3,4,5,6]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7,8]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]; //define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];