add _1, impl combinations
This commit is contained in:
parent
fbf0bfff21
commit
4a4751dcb2
6 changed files with 229 additions and 32 deletions
41
src/combinations.rs
Normal file
41
src/combinations.rs
Normal 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))
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
($f:ident, ( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => {
|
||||
impl< $($t,)* > LensView<( $($t,)* )> for _0 {
|
||||
impl< $($t,)* > LensView<( $($t,)* )> for _0Inner {
|
||||
type Field = T;
|
||||
|
||||
fn view(( $($v,)* ): ($($t,)*)) -> Self::Field {
|
||||
$f
|
||||
}
|
||||
}
|
||||
impl< $($t,)* > LensOver<( $($t,)* )> for _0 {
|
||||
impl< $($t,)* > LensOver<( $($t,)* )> for _0Inner {
|
||||
fn over<F>(
|
||||
mut tup: ($($t,)*),
|
||||
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;
|
||||
|
||||
fn view(( $($v,)* ): &'a ($($t,)*)) -> Self::Field {
|
||||
$f
|
||||
}
|
||||
}
|
||||
impl<'a, $($t,)* > LensView<&'a mut ( $($t,)* )> for _0 {
|
||||
impl<'a, $($t,)* > LensView<&'a mut ( $($t,)* )> for _0Inner {
|
||||
type Field = &'a mut T;
|
||||
|
||||
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 {
|
||||
($f:ident, $n:expr, [$( $v:ident ),*]) => {
|
||||
impl<T> LensView<[T; $n]> for _0 {
|
||||
impl<T> LensView<[T; $n]> for _0Inner {
|
||||
type Field = T;
|
||||
|
||||
fn view([ $($v,)* ]: [T; $n]) -> Self::Field {
|
||||
$f
|
||||
}
|
||||
}
|
||||
impl<T> LensOver<[T; $n]> for _0 {
|
||||
impl<T> LensOver<[T; $n]> for _0Inner {
|
||||
fn over<F>(
|
||||
tup: [T; $n],
|
||||
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;
|
||||
|
||||
fn view([ $($v,)* ]: &'a [T; $n]) -> Self::Field {
|
||||
$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;
|
||||
|
||||
fn view([ $($v,)* ]: &'a mut [T; $n]) -> Self::Field {
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
use crate::{LensOver, LensView};
|
||||
use crate::{LensOver, LensTrait, LensView};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct id;
|
||||
|
||||
impl<T> LensView<T> for T {
|
||||
impl LensTrait for id {}
|
||||
impl<T> LensView<T> for id {
|
||||
type Field = T;
|
||||
|
||||
fn view(thing: T) -> Self::Field {
|
||||
thing
|
||||
}
|
||||
}
|
||||
impl<T> LensOver<T> for T {
|
||||
impl<T> LensOver<T> for id {
|
||||
fn over<F>(thing: T, f: F) -> T
|
||||
where
|
||||
F: FnOnce(Self::Field) -> Self::Field,
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
mod identity;
|
||||
pub use identity::id;
|
||||
|
||||
mod first;
|
||||
pub use first::_0;
|
||||
mod second;
|
||||
pub use second::_1;
|
||||
|
|
99
src/lenses/second.rs
Normal file
99
src/lenses/second.rs
Normal 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]);
|
89
src/lib.rs
89
src/lib.rs
|
@ -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;
|
||||
|
||||
fn view(thing: T) -> Self::Field;
|
||||
}
|
||||
|
||||
/// For lenses that allow setting
|
||||
pub trait LensOver<T>: LensView<T> {
|
||||
fn over<F>(thing: T, f: F) -> T
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
// TODO add Fn implementation for lenses
|
||||
// with one param it should be view, with two it should be over
|
||||
// TODO add std::ops::Add to combine lenses
|
||||
mod combinations;
|
||||
|
||||
// TODO add second_from_tuple, etc
|
||||
// TODO add fn impls
|
||||
|
||||
// TODO add third_from_tuple, etc
|
||||
|
||||
// TODO array traversals
|
||||
|
||||
|
@ -38,17 +69,16 @@ pub mod lenses;
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{lenses::_0, *};
|
||||
use super::{
|
||||
lenses::{_0, _1},
|
||||
*,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn view_first_from_tuple() {
|
||||
let a = (1, 2);
|
||||
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);
|
||||
assert_eq!(view(_0, &a), &1);
|
||||
|
||||
|
@ -75,10 +105,6 @@ mod tests {
|
|||
let a = (1, 2);
|
||||
let a = set(_0, a, 3);
|
||||
assert_eq!(a, (3, 2));
|
||||
|
||||
let a = (1, 2);
|
||||
let a = _0::set(a, 3);
|
||||
assert_eq!(a, (3, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -86,17 +112,42 @@ mod tests {
|
|||
let a = (1, 2);
|
||||
let a = over(_0, a, |v| v + 1);
|
||||
assert_eq!(a, (2, 2));
|
||||
|
||||
let a = (1, 2);
|
||||
let a = _0::over(a, |v| v + 1);
|
||||
assert_eq!(a, (2, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn over_first_from_array() {
|
||||
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]);
|
||||
}
|
||||
|
||||
#[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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue