add _1, impl combinations

main
annieversary 2021-11-05 13:27:34 +00:00
parent fbf0bfff21
commit 4a4751dcb2
6 changed files with 229 additions and 32 deletions

41
src/combinations.rs Normal file
View File

@ -0,0 +1,41 @@
use crate::{Lens, LensOver, LensTrait, LensView};
pub struct Combination<A, B>(A, B);
impl<A, B> LensTrait for Combination<A, B> {}
impl<A, B> std::ops::Add<Lens<B>> for Lens<A>
where
A: LensTrait,
B: LensTrait,
{
type Output = Lens<Combination<Lens<A>, Lens<B>>>;
fn add(self, rhs: Lens<B>) -> Self::Output {
Lens(Combination(self, rhs))
}
}
impl<A, B, T> LensView<T> for Combination<A, B>
where
A: LensView<T>,
B: LensView<A::Field>,
{
type Field = B::Field;
fn view(thing: T) -> Self::Field {
B::view(A::view(thing))
}
}
impl<A, B, T> LensOver<T> for Combination<A, B>
where
A: LensOver<T>,
B: LensOver<A::Field>,
{
fn over<F>(thing: T, f: F) -> T
where
F: FnOnce(Self::Field) -> Self::Field,
{
A::over(thing, |b| B::over(b, f))
}
}

View File

@ -1,17 +1,19 @@
use crate::{LensOver, LensView}; use crate::{Lens, LensOver, LensTrait, LensView};
pub struct _0; pub struct _0Inner;
pub const _0: Lens<_0Inner> = Lens(_0Inner);
impl LensTrait for _0Inner {}
macro_rules! make_tuples { macro_rules! make_tuples {
($f:ident, ( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => { ($f:ident, ( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => {
impl< $($t,)* > LensView<( $($t,)* )> for _0 { impl< $($t,)* > LensView<( $($t,)* )> for _0Inner {
type Field = T; type Field = T;
fn view(( $($v,)* ): ($($t,)*)) -> Self::Field { fn view(( $($v,)* ): ($($t,)*)) -> Self::Field {
$f $f
} }
} }
impl< $($t,)* > LensOver<( $($t,)* )> for _0 { impl< $($t,)* > LensOver<( $($t,)* )> for _0Inner {
fn over<F>( fn over<F>(
mut tup: ($($t,)*), mut tup: ($($t,)*),
f: F f: F
@ -24,14 +26,14 @@ macro_rules! make_tuples {
} }
} }
impl<'a, $($t,)* > LensView<&'a ( $($t,)* )> for _0 { impl<'a, $($t,)* > LensView<&'a ( $($t,)* )> for _0Inner {
type Field = &'a T; type Field = &'a T;
fn view(( $($v,)* ): &'a ($($t,)*)) -> Self::Field { fn view(( $($v,)* ): &'a ($($t,)*)) -> Self::Field {
$f $f
} }
} }
impl<'a, $($t,)* > LensView<&'a mut ( $($t,)* )> for _0 { impl<'a, $($t,)* > LensView<&'a mut ( $($t,)* )> for _0Inner {
type Field = &'a mut T; type Field = &'a mut T;
fn view(( $($v,)* ): &'a mut ($($t,)*)) -> Self::Field { fn view(( $($v,)* ): &'a mut ($($t,)*)) -> Self::Field {
@ -51,14 +53,14 @@ make_tuples!(t, (t, _u, _v, _w, _x, _y, _z), (T, U, V, W, X, Y, Z));
macro_rules! make_arrays { macro_rules! make_arrays {
($f:ident, $n:expr, [$( $v:ident ),*]) => { ($f:ident, $n:expr, [$( $v:ident ),*]) => {
impl<T> LensView<[T; $n]> for _0 { impl<T> LensView<[T; $n]> for _0Inner {
type Field = T; type Field = T;
fn view([ $($v,)* ]: [T; $n]) -> Self::Field { fn view([ $($v,)* ]: [T; $n]) -> Self::Field {
$f $f
} }
} }
impl<T> LensOver<[T; $n]> for _0 { impl<T> LensOver<[T; $n]> for _0Inner {
fn over<F>( fn over<F>(
tup: [T; $n], tup: [T; $n],
fun: F fun: F
@ -72,14 +74,14 @@ macro_rules! make_arrays {
} }
} }
impl<'a, T> LensView<&'a [T; $n]> for _0 { impl<'a, T> LensView<&'a [T; $n]> for _0Inner {
type Field = &'a T; type Field = &'a T;
fn view([ $($v,)* ]: &'a [T; $n]) -> Self::Field { fn view([ $($v,)* ]: &'a [T; $n]) -> Self::Field {
$f $f
} }
} }
impl<'a, T> LensView<&'a mut [T; $n]> for _0 { impl<'a, T> LensView<&'a mut [T; $n]> for _0Inner {
type Field = &'a mut T; type Field = &'a mut T;
fn view([ $($v,)* ]: &'a mut [T; $n]) -> Self::Field { fn view([ $($v,)* ]: &'a mut [T; $n]) -> Self::Field {

View File

@ -1,16 +1,17 @@
use crate::{LensOver, LensView}; use crate::{LensOver, LensTrait, LensView};
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct id; pub struct id;
impl<T> LensView<T> for T { impl LensTrait for id {}
impl<T> LensView<T> for id {
type Field = T; type Field = T;
fn view(thing: T) -> Self::Field { fn view(thing: T) -> Self::Field {
thing thing
} }
} }
impl<T> LensOver<T> for T { impl<T> LensOver<T> for id {
fn over<F>(thing: T, f: F) -> T fn over<F>(thing: T, f: F) -> T
where where
F: FnOnce(Self::Field) -> Self::Field, F: FnOnce(Self::Field) -> Self::Field,

View File

@ -1,4 +1,7 @@
mod identity; mod identity;
pub use identity::id; pub use identity::id;
mod first; mod first;
pub use first::_0; pub use first::_0;
mod second;
pub use second::_1;

99
src/lenses/second.rs Normal file
View File

@ -0,0 +1,99 @@
use crate::{Lens, LensOver, LensTrait, LensView};
pub struct _1Inner;
pub const _1: Lens<_1Inner> = Lens(_1Inner);
impl LensTrait for _1Inner {}
macro_rules! make_tuples {
($f:ident, ( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => {
impl< $($t,)* > LensView<( $($t,)* )> for _1Inner {
type Field = T;
fn view(( $($v,)* ): ($($t,)*)) -> Self::Field {
$f
}
}
impl< $($t,)* > LensOver<( $($t,)* )> for _1Inner {
fn over<F>(
mut tup: ($($t,)*),
f: F
) -> ( $($t,)* )
where
F: FnOnce(Self::Field) -> Self::Field
{
tup.1 = f(tup.1);
tup
}
}
impl<'a, $($t,)* > LensView<&'a ( $($t,)* )> for _1Inner {
type Field = &'a T;
fn view(( $($v,)* ): &'a ($($t,)*)) -> Self::Field {
$f
}
}
impl<'a, $($t,)* > LensView<&'a mut ( $($t,)* )> for _1Inner {
type Field = &'a mut T;
fn view(( $($v,)* ): &'a mut ($($t,)*)) -> Self::Field {
$f
}
}
};
}
make_tuples!(t, (_u, t), (U, T));
make_tuples!(t, (_u, t, _v), (U, T, V));
make_tuples!(t, (_u, t, _v, _w), (U, T, V, W));
make_tuples!(t, (_u, t, _v, _w, _x), (U, T, V, W, X));
make_tuples!(t, (_u, t, _v, _w, _x, _y), (U, T, V, W, X, Y));
make_tuples!(t, (_u, t, _v, _w, _x, _y, _z), (U, T, V, W, X, Y, Z));
// 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> LensView<[T; $n]> for _1Inner {
type Field = T;
fn view([ $($v,)* ]: [T; $n]) -> Self::Field {
$f
}
}
impl<T> LensOver<[T; $n]> for _1Inner {
fn over<F>(
tup: [T; $n],
fun: F
) -> [T; $n]
where
F: FnOnce(Self::Field) -> Self::Field
{
let [$($v,)*] = tup;
let $f = fun( $f );
[$($v,)*]
}
}
impl<'a, T> LensView<&'a [T; $n]> for _1Inner {
type Field = &'a T;
fn view([ $($v,)* ]: &'a [T; $n]) -> Self::Field {
$f
}
}
impl<'a, T> LensView<&'a mut [T; $n]> for _1Inner {
type Field = &'a mut T;
fn view([ $($v,)* ]: &'a mut [T; $n]) -> Self::Field {
$f
}
}
};
}
make_arrays!(t, 2, [_a, t]);
make_arrays!(t, 3, [_a, t, _b]);
make_arrays!(t, 4, [_a, t, _b, _c]);
make_arrays!(t, 5, [_a, t, _b, _c, _d]);
make_arrays!(t, 6, [_a, t, _b, _c, _d, _e]);
make_arrays!(t, 7, [_a, t, _b, _c, _d, _e, _g]);

View File

@ -1,9 +1,14 @@
pub trait LensView<T> { /// Base trait
pub trait LensTrait {}
/// For lenses that allow viewing
pub trait LensView<T>: LensTrait {
type Field; type Field;
fn view(thing: T) -> Self::Field; fn view(thing: T) -> Self::Field;
} }
/// For lenses that allow setting
pub trait LensOver<T>: LensView<T> { pub trait LensOver<T>: LensView<T> {
fn over<F>(thing: T, f: F) -> T fn over<F>(thing: T, f: F) -> T
where where
@ -14,6 +19,32 @@ pub trait LensOver<T>: LensView<T> {
} }
} }
/// Wrapper type
pub struct Lens<T: LensTrait>(T);
impl<L: LensTrait> LensTrait for Lens<L> {}
impl<L, T> LensView<T> for Lens<L>
where
L: LensView<T>,
{
type Field = L::Field;
fn view(thing: T) -> Self::Field {
L::view(thing)
}
}
impl<L, T> LensOver<T> for Lens<L>
where
L: LensOver<T>,
{
fn over<F>(thing: T, f: F) -> T
where
F: FnOnce(Self::Field) -> Self::Field,
{
L::over(thing, f)
}
}
pub fn view<T, L: LensView<T>>(_lens: L, thing: T) -> L::Field { pub fn view<T, L: LensView<T>>(_lens: L, thing: T) -> L::Field {
L::view(thing) L::view(thing)
} }
@ -24,11 +55,11 @@ pub fn over<T, L: LensOver<T>>(_lens: L, thing: T, f: impl FnOnce(L::Field) -> L
L::over(thing, f) L::over(thing, f)
} }
// TODO add Fn implementation for lenses mod combinations;
// with one param it should be view, with two it should be over
// TODO add std::ops::Add to combine lenses
// TODO add second_from_tuple, etc // TODO add fn impls
// TODO add third_from_tuple, etc
// TODO array traversals // TODO array traversals
@ -38,17 +69,16 @@ pub mod lenses;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{lenses::_0, *}; use super::{
lenses::{_0, _1},
*,
};
#[test] #[test]
fn view_first_from_tuple() { fn view_first_from_tuple() {
let a = (1, 2); let a = (1, 2);
assert_eq!(view(_0, a), 1); assert_eq!(view(_0, a), 1);
// you can call it both ways
let a = (1, 2);
assert_eq!(_0::view(a), 1);
let a = (1, 2); let a = (1, 2);
assert_eq!(view(_0, &a), &1); assert_eq!(view(_0, &a), &1);
@ -75,10 +105,6 @@ mod tests {
let a = (1, 2); let a = (1, 2);
let a = set(_0, a, 3); let a = set(_0, a, 3);
assert_eq!(a, (3, 2)); assert_eq!(a, (3, 2));
let a = (1, 2);
let a = _0::set(a, 3);
assert_eq!(a, (3, 2));
} }
#[test] #[test]
@ -86,17 +112,42 @@ mod tests {
let a = (1, 2); let a = (1, 2);
let a = over(_0, a, |v| v + 1); let a = over(_0, a, |v| v + 1);
assert_eq!(a, (2, 2)); assert_eq!(a, (2, 2));
let a = (1, 2);
let a = _0::over(a, |v| v + 1);
assert_eq!(a, (2, 2));
} }
#[test] #[test]
fn over_first_from_array() { fn over_first_from_array() {
let a = [1, 2, 3, 4]; let a = [1, 2, 3, 4];
let a = _0::over(a, |v| v + 1); let a = over(_0, a, |v| v + 1);
assert_eq!(a, [2, 2, 3, 4]); assert_eq!(a, [2, 2, 3, 4]);
} }
#[test]
fn second() {
let a = (1, 2);
let a = over(_1, a, |v| v + 1);
assert_eq!(a, (1, 3));
let a = [1, 2, 3, 4];
let a = over(_1, a, |v| v + 1);
assert_eq!(a, [1, 3, 3, 4]);
}
#[test]
fn view_combination() {
let a = ((1, 2), 3);
let lens = _0 + _1;
let a = view(lens, a);
assert_eq!(a, 2);
}
#[test]
fn over_combination() {
let a = ((1, 2), 3);
let lens = _0 + _1;
let a = over(lens, a, |v| v + 1);
assert_eq!(a, ((1, 3), 3));
}
} }