add traversals
parent
e6163ea626
commit
e5a9293ec2
|
@ -5,6 +5,7 @@ pub trait OpticsTrait {}
|
||||||
|
|
||||||
/// Wrapper type
|
/// Wrapper type
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct Optics<T: OpticsTrait>(pub(crate) T);
|
pub struct Optics<T: OpticsTrait>(pub(crate) T);
|
||||||
impl<L: OpticsTrait> OpticsTrait for Optics<L> {}
|
impl<L: OpticsTrait> OpticsTrait for Optics<L> {}
|
||||||
|
|
||||||
|
@ -12,3 +13,4 @@ mod combinations;
|
||||||
mod fns;
|
mod fns;
|
||||||
pub mod lenses;
|
pub mod lenses;
|
||||||
pub mod prisms;
|
pub mod prisms;
|
||||||
|
pub mod traversals;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::{Optics, OpticsTrait};
|
use crate::{Optics, OpticsTrait};
|
||||||
|
|
||||||
/// For lenses that allow viewing
|
|
||||||
pub trait PrismPreview<T>: OpticsTrait {
|
pub trait PrismPreview<T>: OpticsTrait {
|
||||||
type Field;
|
type Field;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
use crate::{
|
||||||
|
traversals::{TraversalOver, TraversalTraverse},
|
||||||
|
Optics, OpticsTrait,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct BothInner;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
pub const both: Optics<BothInner> = Optics(BothInner);
|
||||||
|
impl OpticsTrait for BothInner {}
|
||||||
|
|
||||||
|
impl<T> TraversalTraverse<(T, T)> for BothInner {
|
||||||
|
type Field = T;
|
||||||
|
|
||||||
|
fn traverse(&self, (a, b): (T, T)) -> Vec<Self::Field> {
|
||||||
|
vec![a, b]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> TraversalOver<(T, T)> for BothInner {
|
||||||
|
fn over<F>(&self, (a, b): (T, T), mut f: F) -> (T, T)
|
||||||
|
where
|
||||||
|
F: FnMut(Self::Field) -> Self::Field,
|
||||||
|
{
|
||||||
|
(f(a), f(b))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
use crate::{
|
||||||
|
traversals::{TraversalOver, TraversalTraverse},
|
||||||
|
Optics, OpticsTrait,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct EachInner;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
pub const each: Optics<EachInner> = Optics(EachInner);
|
||||||
|
impl OpticsTrait for EachInner {}
|
||||||
|
|
||||||
|
impl<T> TraversalTraverse<Vec<T>> for EachInner {
|
||||||
|
type Field = T;
|
||||||
|
|
||||||
|
fn traverse(&self, thing: Vec<T>) -> Vec<Self::Field> {
|
||||||
|
thing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> TraversalOver<Vec<T>> for EachInner {
|
||||||
|
fn over<F>(&self, thing: Vec<T>, f: F) -> Vec<T>
|
||||||
|
where
|
||||||
|
F: FnMut(Self::Field) -> Self::Field,
|
||||||
|
{
|
||||||
|
thing.into_iter().map(f).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! make_tuples {
|
||||||
|
($f:ident, ( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => {
|
||||||
|
impl<T> TraversalTraverse<( $($t,)* )> for EachInner {
|
||||||
|
type Field = T;
|
||||||
|
|
||||||
|
fn traverse(&self, ( $($v,)* ): ($($t,)*)) -> Vec<Self::Field> {
|
||||||
|
vec![ $($v,)* ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T> TraversalOver<( $($t,)* )> for EachInner {
|
||||||
|
fn over<F>(
|
||||||
|
&self,
|
||||||
|
($($v,)*): ($($t,)*),
|
||||||
|
mut f: F
|
||||||
|
) -> ( $($t,)* )
|
||||||
|
where
|
||||||
|
F: FnMut(Self::Field) -> Self::Field
|
||||||
|
{
|
||||||
|
|
||||||
|
( $( f($v), )* )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> TraversalTraverse<&'a ( $($t,)* )> for EachInner {
|
||||||
|
type Field = &'a T;
|
||||||
|
|
||||||
|
fn traverse(&self, ( $($v,)* ): &'a ($($t,)*)) -> Vec<Self::Field> {
|
||||||
|
vec![ $($v,)* ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a, T> TraversalTraverse<&'a mut ( $($t,)* )> for EachInner {
|
||||||
|
type Field = &'a mut T;
|
||||||
|
|
||||||
|
fn traverse(&self, ( $($v,)* ): &'a mut ($($t,)*)) -> Vec<Self::Field> {
|
||||||
|
vec![ $($v,)* ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
make_tuples!(t, (t), (T));
|
||||||
|
make_tuples!(t, (t, u), (T, T));
|
||||||
|
make_tuples!(t, (t, u, v), (T, T, T));
|
||||||
|
make_tuples!(t, (t, u, v, w), (T, T, T, T));
|
||||||
|
make_tuples!(t, (t, u, v, w, x), (T, T, T, T, T));
|
||||||
|
make_tuples!(t, (t, u, v, w, x, y), (T, T, T, T, T, T));
|
||||||
|
make_tuples!(t, (t, u, v, w, x, y, z), (T, T, T, T, T, T, T));
|
||||||
|
// not doing more cause i'm lazy, open a pr if you need more :)
|
||||||
|
|
||||||
|
macro_rules! make_arrays {
|
||||||
|
($f:ident, $n:expr, [$( $v:ident ),*]) => {
|
||||||
|
impl<T> TraversalTraverse<[T; $n]> for EachInner {
|
||||||
|
type Field = T;
|
||||||
|
|
||||||
|
fn traverse(&self, [ $($v,)* ]: [T; $n]) -> Vec<Self::Field> {
|
||||||
|
vec![ $($v,)* ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T> TraversalOver<[T; $n]> for EachInner {
|
||||||
|
fn over<F>(
|
||||||
|
&self,
|
||||||
|
[ $($v,)* ]: [T; $n],
|
||||||
|
mut fun: F
|
||||||
|
) -> [T; $n]
|
||||||
|
where
|
||||||
|
F: FnMut(Self::Field) -> Self::Field
|
||||||
|
{
|
||||||
|
[$(fun($v),)*]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> TraversalTraverse<&'a [T; $n]> for EachInner {
|
||||||
|
type Field = &'a T;
|
||||||
|
|
||||||
|
fn traverse(&self, [ $($v,)* ]: &'a [T; $n]) -> Vec<Self::Field> {
|
||||||
|
vec![ $($v,)* ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a, T> TraversalTraverse<&'a mut [T; $n]> for EachInner {
|
||||||
|
type Field = &'a mut T;
|
||||||
|
|
||||||
|
fn traverse(&self, [ $($v,)* ]: &'a mut [T; $n]) -> Vec<Self::Field> {
|
||||||
|
vec![ $($v,)* ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
make_arrays!(t, 1, [t]);
|
||||||
|
make_arrays!(t, 2, [t, _a]);
|
||||||
|
make_arrays!(t, 3, [t, _a, _b]);
|
||||||
|
make_arrays!(t, 4, [t, _a, _b, _c]);
|
||||||
|
make_arrays!(t, 5, [t, _a, _b, _c, _d]);
|
||||||
|
make_arrays!(t, 6, [t, _a, _b, _c, _d, _e]);
|
||||||
|
make_arrays!(t, 7, [t, _a, _b, _c, _d, _e, _g]);
|
|
@ -0,0 +1,98 @@
|
||||||
|
use crate::{Optics, OpticsTrait};
|
||||||
|
|
||||||
|
mod both;
|
||||||
|
pub use both::both;
|
||||||
|
|
||||||
|
mod each;
|
||||||
|
pub use each::each;
|
||||||
|
|
||||||
|
/// For lenses that allow viewing
|
||||||
|
pub trait TraversalTraverse<T>: OpticsTrait {
|
||||||
|
type Field;
|
||||||
|
|
||||||
|
fn traverse(&self, thing: T) -> Vec<Self::Field>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For lenses that allow setting
|
||||||
|
pub trait TraversalOver<T>: TraversalTraverse<T> {
|
||||||
|
fn over<F>(&self, thing: T, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnMut(Self::Field) -> Self::Field;
|
||||||
|
|
||||||
|
fn set(&self, thing: T, v: Self::Field) -> T
|
||||||
|
where
|
||||||
|
Self::Field: Clone,
|
||||||
|
{
|
||||||
|
Self::over(self, thing, move |_| v.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<L, T> TraversalTraverse<T> for Optics<L>
|
||||||
|
where
|
||||||
|
L: TraversalTraverse<T>,
|
||||||
|
{
|
||||||
|
type Field = L::Field;
|
||||||
|
|
||||||
|
fn traverse(&self, thing: T) -> Vec<Self::Field> {
|
||||||
|
L::traverse(&self.0, thing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<L, T> TraversalOver<T> for Optics<L>
|
||||||
|
where
|
||||||
|
L: TraversalOver<T>,
|
||||||
|
{
|
||||||
|
fn over<F>(&self, thing: T, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnMut(Self::Field) -> Self::Field,
|
||||||
|
{
|
||||||
|
L::over(&self.0, thing, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // every lens is also a traversal
|
||||||
|
// impl<L, T> TraversalTraverse<T> for Optics<L>
|
||||||
|
// where
|
||||||
|
// L: LensView<T>,
|
||||||
|
// {
|
||||||
|
// type Field = L::Field;
|
||||||
|
|
||||||
|
// fn traverse(&self, thing: T) -> Vec<Self::Field> {
|
||||||
|
// vec![L::view(&self.0, thing)]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl<L, T> TraversalOver<T> for Optics<L>
|
||||||
|
// where
|
||||||
|
// L: LensOver<T>,
|
||||||
|
// {
|
||||||
|
// fn over<F>(&self, thing: T, f: F) -> T
|
||||||
|
// where
|
||||||
|
// F: FnMut(Self::Field) -> Self::Field,
|
||||||
|
// {
|
||||||
|
// L::over(&self.0, thing, f)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn traverse<T, L: TraversalTraverse<T>>(lens: L, thing: T) -> Vec<L::Field> {
|
||||||
|
L::traverse(&lens, thing)
|
||||||
|
}
|
||||||
|
pub fn set<T, L: TraversalOver<T>>(lens: L, thing: T, v: L::Field) -> T
|
||||||
|
where
|
||||||
|
<L as TraversalTraverse<T>>::Field: Clone,
|
||||||
|
{
|
||||||
|
L::set(&lens, thing, v)
|
||||||
|
}
|
||||||
|
pub fn over<T, L: TraversalOver<T>>(lens: L, thing: T, f: impl FnMut(L::Field) -> L::Field) -> T {
|
||||||
|
L::over(&lens, thing, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn traverse_each_works_on_arrays() {
|
||||||
|
let array = [1, 2, 3, 4];
|
||||||
|
|
||||||
|
let res = over(each, array, |v| v + 1);
|
||||||
|
assert_eq!(res, [2, 3, 4, 5]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue