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))
}
}