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
use std::rc::Rc; use rust_fp_categories::*; use rust_fp_categories::empty::Empty; use rust_fp_categories::hkt::HKT; use set::Set; #[derive(Debug, PartialEq, PartialOrd)] pub enum Tree<A> { Empty, Cons(Rc<Self>, A, Rc<Self>), } derive_hkt!(Tree); impl<A> Tree<A> { fn cons(left: Self, value: A, right: Self) -> Self { Tree::Cons(Rc::new(left), value, Rc::new(right)) } } impl<A> Empty for Tree<A> { fn empty() -> Self { Tree::Empty } fn is_empty(&self) -> bool { match self { &Tree::Empty => true, &Tree::Cons(..) => false, } } } impl<A: PartialEq + PartialOrd> Set<A> for Tree<A> { fn insert(self, value: A) -> Self { fn insert_to<A: PartialEq + PartialOrd>( x: A, s_arc: Rc<Tree<A>>, ) -> Option<Rc<Tree<A>>> { let s = Rc::try_unwrap(s_arc).unwrap_or(Tree::Empty); match s { Tree::Empty => Some(Rc::new(Tree::cons(Tree::Empty, x, Tree::Empty))), Tree::Cons(a, y, b) => { if x < y { insert_to(x, a).map(|a| Rc::new(Tree::Cons(a, y, b))) } else if y < x { insert_to(x, b).map(|b| Rc::new(Tree::Cons(a, y, b))) } else { None } } } } let target = Rc::new(self); let default = Rc::clone(&target); let result = insert_to(value, target).unwrap_or(default); Rc::try_unwrap(result).unwrap_or(Tree::Empty) } fn member(self, value: A) -> bool { fn member1<A: PartialEq + PartialOrd>( x: A, last: Option<A>, ss_arc: Rc<Tree<A>>, ) -> bool { let ss = Rc::try_unwrap(ss_arc).unwrap_or(Tree::Empty); match ss { Tree::Empty => last.iter().any(|y| x == *y), Tree::Cons(a, y, b) => { if x < y { member1(x, last, a) } else { member1(x, Some(y), b) } } } } member1(value, None, Rc::new(self)) } } #[cfg(test)] mod tests { use stack::StackError; #[test] fn test() -> Result<(), StackError> { Ok(()) } }