use crate::{ lenses::{Lens, LensOver, LensView}, traversals::{Traversal, TraversalOver, TraversalTraverse}, }; #[derive(Clone, Copy)] pub struct Combination(A, B); // additions impl std::ops::Add> for Lens { type Output = Lens, Lens>>; fn add(self, rhs: Lens) -> Self::Output { Lens(Combination(self, rhs)) } } impl std::ops::Add> for Traversal { type Output = Traversal, Traversal>>; fn add(self, rhs: Traversal) -> Self::Output { Traversal(Combination(self, rhs)) } } impl std::ops::Add> for Traversal { type Output = Traversal, Traversal>>>; fn add(self, rhs: Lens) -> Self::Output { Traversal(Combination(self, rhs.to_traversal())) } } impl std::ops::Add> for Lens { type Output = Traversal>, Traversal>>; fn add(self, rhs: Traversal) -> Self::Output { Traversal(Combination(self.to_traversal(), rhs)) } } // trait impls for Combination impl LensView for Combination where A: LensView, B: LensView, { type Field = B::Field; fn view(&self, thing: T) -> Self::Field { B::view(&self.1, A::view(&self.0, thing)) } } impl LensOver for Combination where A: LensOver, B: LensOver, { fn over(&self, thing: T, f: F) -> T where F: FnOnce(Self::Field) -> Self::Field, { A::over(&self.0, thing, |b| B::over(&self.1, b, f)) } } impl TraversalTraverse for Combination where A: TraversalTraverse, B: TraversalTraverse, { type Field = B::Field; fn traverse(&self, thing: T) -> Vec { let a = A::traverse(&self.0, thing); a.into_iter() .map(|v| B::traverse(&self.1, v)) .flatten() .collect() } } impl TraversalOver for Combination where A: TraversalOver, B: TraversalOver, { fn over(&self, thing: T, mut f: F) -> T where F: FnMut(Self::Field) -> Self::Field, { A::over(&self.0, thing, |b| B::over(&self.1, b, &mut f)) } }