diff --git a/src/combinations.rs b/src/combinations.rs index fe6411b..60eee2b 100644 --- a/src/combinations.rs +++ b/src/combinations.rs @@ -1,21 +1,13 @@ -use crate::{ - lenses::{LensOver, LensView}, - Optics, OpticsTrait, -}; +use crate::lenses::{Lens, LensOver, LensView}; #[derive(Clone, Copy)] pub struct Combination(A, B); -impl OpticsTrait for Combination {} -impl std::ops::Add> for Optics -where - A: OpticsTrait, - B: OpticsTrait, -{ - type Output = Optics, Optics>>; +impl std::ops::Add> for Lens { + type Output = Lens, Lens>>; - fn add(self, rhs: Optics) -> Self::Output { - Optics(Combination(self, rhs)) + fn add(self, rhs: Lens) -> Self::Output { + Lens(Combination(self, rhs)) } } diff --git a/src/fns.rs b/src/fns.rs index a7474ee..88b0cc7 100644 --- a/src/fns.rs +++ b/src/fns.rs @@ -1,9 +1,10 @@ use crate::{ - lenses::{LensOver, LensView}, - Optics, + lenses::{Lens, LensOver, LensView}, + traversals::{Traversal, TraversalOver, TraversalTraverse}, }; -impl std::ops::FnOnce<(A,)> for Optics +// lens view +impl std::ops::FnOnce<(A,)> for Lens where L: LensView, { @@ -13,7 +14,7 @@ where L::view(&self.0, args.0) } } -impl std::ops::FnMut<(A,)> for Optics +impl std::ops::FnMut<(A,)> for Lens where L: LensView, { @@ -21,7 +22,7 @@ where L::view(&self.0, args.0) } } -impl std::ops::Fn<(A,)> for Optics +impl std::ops::Fn<(A,)> for Lens where L: LensView, { @@ -30,7 +31,8 @@ where } } -impl std::ops::FnOnce<(A, F)> for Optics +// lens over +impl std::ops::FnOnce<(A, F)> for Lens where L: LensOver, F: FnOnce(L::Field) -> L::Field, @@ -41,7 +43,7 @@ where L::over(&self.0, args.0, args.1) } } -impl std::ops::FnMut<(A, F)> for Optics +impl std::ops::FnMut<(A, F)> for Lens where L: LensOver, F: FnOnce(L::Field) -> L::Field, @@ -50,7 +52,7 @@ where L::over(&self.0, args.0, args.1) } } -impl std::ops::Fn<(A, F)> for Optics +impl std::ops::Fn<(A, F)> for Lens where L: LensOver, F: FnOnce(L::Field) -> L::Field, @@ -59,3 +61,62 @@ where L::over(&self.0, args.0, args.1) } } + +// traversal traverse +impl std::ops::FnOnce<(A,)> for Traversal +where + L: TraversalTraverse, +{ + type Output = Vec; + + extern "rust-call" fn call_once(self, args: (A,)) -> Self::Output { + L::traverse(&self.0, args.0) + } +} +impl std::ops::FnMut<(A,)> for Traversal +where + L: TraversalTraverse, +{ + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> Self::Output { + L::traverse(&self.0, args.0) + } +} +impl std::ops::Fn<(A,)> for Traversal +where + L: TraversalTraverse, +{ + extern "rust-call" fn call(&self, args: (A,)) -> Self::Output { + L::traverse(&self.0, args.0) + } +} + +// traversal over +impl std::ops::FnOnce<(A, F)> for Traversal +where + L: TraversalOver, + F: FnMut(L::Field) -> L::Field, +{ + type Output = A; + + extern "rust-call" fn call_once(self, args: (A, F)) -> Self::Output { + L::over(&self.0, args.0, args.1) + } +} +impl std::ops::FnMut<(A, F)> for Traversal +where + L: TraversalOver, + F: FnMut(L::Field) -> L::Field, +{ + extern "rust-call" fn call_mut(&mut self, args: (A, F)) -> Self::Output { + L::over(&self.0, args.0, args.1) + } +} +impl std::ops::Fn<(A, F)> for Traversal +where + L: TraversalOver, + F: FnMut(L::Field) -> L::Field, +{ + extern "rust-call" fn call(&self, args: (A, F)) -> Self::Output { + L::over(&self.0, args.0, args.1) + } +} diff --git a/src/lenses/first.rs b/src/lenses/first.rs index 1358f71..698f731 100644 --- a/src/lenses/first.rs +++ b/src/lenses/first.rs @@ -1,12 +1,8 @@ -use crate::{ - lenses::{LensOver, LensView}, - Optics, OpticsTrait, -}; +use crate::lenses::{Lens, LensOver, LensView}; #[derive(Clone, Copy)] pub struct _0Inner; -pub const _0: Optics<_0Inner> = Optics(_0Inner); -impl OpticsTrait for _0Inner {} +pub const _0: Lens<_0Inner> = Lens(_0Inner); macro_rules! make_tuples { ($f:ident, ( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => { diff --git a/src/lenses/identity.rs b/src/lenses/identity.rs index 4af9104..1fb21ad 100644 --- a/src/lenses/identity.rs +++ b/src/lenses/identity.rs @@ -1,21 +1,18 @@ -use crate::{ - lenses::{LensOver, LensView}, - OpticsTrait, -}; +use crate::lenses::{Lens, LensOver, LensView}; -#[allow(non_camel_case_types)] #[derive(Clone, Copy)] -pub struct id; +pub struct IdInner; +#[allow(non_upper_case_globals)] +pub const id: Lens = Lens(IdInner); -impl OpticsTrait for id {} -impl LensView for id { +impl LensView for IdInner { type Field = T; fn view(&self, thing: T) -> Self::Field { thing } } -impl LensOver for id { +impl LensOver for IdInner { fn over(&self, thing: T, f: F) -> T where F: FnOnce(Self::Field) -> Self::Field, diff --git a/src/lenses/lens.rs b/src/lenses/lens.rs index 5828290..aa83efc 100644 --- a/src/lenses/lens.rs +++ b/src/lenses/lens.rs @@ -1,13 +1,9 @@ -use crate::{ - lenses::{LensOver, LensView}, - Optics, OpticsTrait, -}; +use crate::lenses::{Lens, LensOver, LensView}; type Getter = dyn Fn(T) -> U; type Setter = dyn Fn(T, U) -> T; pub struct LensInner(pub(crate) Box>, pub(crate) Box>); -impl OpticsTrait for LensInner {} impl LensView for LensInner { type Field = U; @@ -34,13 +30,13 @@ impl LensOver for LensInner { pub fn lens_from_boxed( getter: Box>, setter: Box>, -) -> Optics> { - Optics(LensInner(getter, setter)) +) -> Lens> { + Lens(LensInner(getter, setter)) } /// Makes a lens that implements `LensView` and `LensOver` with the provided functions pub fn lens( getter: impl Fn(T) -> U + 'static, setter: impl Fn(T, U) -> T + 'static, -) -> Optics> { - Optics(LensInner(Box::new(getter), Box::new(setter))) +) -> Lens> { + Lens(LensInner(Box::new(getter), Box::new(setter))) } diff --git a/src/lenses/mod.rs b/src/lenses/mod.rs index 12e0563..e6ce140 100644 --- a/src/lenses/mod.rs +++ b/src/lenses/mod.rs @@ -11,10 +11,30 @@ pub use to::{to, to_from_boxed}; mod lens; pub use lens::{lens, lens_from_boxed}; -use crate::{Optics, OpticsTrait}; +use crate::traversals::Traversal; + +/// Wrapper type +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct Lens(pub(crate) L); + +// all lenses are traversals, so we can freely transform them into a traversal +impl Lens { + /// Returns this lens as a traversal + pub fn to_traversal(self) -> Traversal> { + Traversal(self) + } +} +// we can go back to a lens from a "traversal-ed" lens +impl Traversal> { + /// Returns the wrapped lens + pub fn to_lens(self) -> Lens { + self.0 + } +} /// For lenses that allow viewing -pub trait LensView: OpticsTrait { +pub trait LensView { type Field; fn view(&self, thing: T) -> Self::Field; @@ -31,7 +51,7 @@ pub trait LensOver: LensView { } } -impl LensView for Optics +impl LensView for Lens where L: LensView, { @@ -41,7 +61,7 @@ where L::view(&self.0, thing) } } -impl LensOver for Optics +impl LensOver for Lens where L: LensOver, { diff --git a/src/lenses/second.rs b/src/lenses/second.rs index b66a6d6..92af98d 100644 --- a/src/lenses/second.rs +++ b/src/lenses/second.rs @@ -1,23 +1,19 @@ -use crate::{ - lenses::{LensOver, LensView}, - Optics, OpticsTrait, -}; +use crate::lenses::{Lens, LensOver, LensView}; #[derive(Clone, Copy)] pub struct _1Inner; -pub const _1: Optics<_1Inner> = Optics(_1Inner); -impl OpticsTrait for _1Inner {} +pub const _1: Lens<_1Inner> = Lens(_1Inner); macro_rules! make_tuples { ($f:ident, ( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => { - impl< $($t,)* > LensView<( $($t,)* )> for _1Inner { + impl< $($t,)* > LensView<( $($t,)* )> for _1Inner { type Field = T; fn view(&self, ( $($v,)* ): ($($t,)*)) -> Self::Field { $f } } - impl< $($t,)* > LensOver<( $($t,)* )> for _1Inner { + impl< $($t,)* > LensOver<( $($t,)* )> for _1Inner { fn over( &self, mut tup: ($($t,)*), @@ -31,14 +27,14 @@ macro_rules! make_tuples { } } - impl<'a, $($t,)* > LensView<&'a ( $($t,)* )> for _1Inner { + impl<'a, $($t,)* > LensView<&'a ( $($t,)* )> for _1Inner { type Field = &'a T; fn view(&self, ( $($v,)* ): &'a ($($t,)*)) -> Self::Field { $f } } - impl<'a, $($t,)* > LensView<&'a mut ( $($t,)* )> for _1Inner { + impl<'a, $($t,)* > LensView<&'a mut ( $($t,)* )> for _1Inner { type Field = &'a mut T; fn view(&self, ( $($v,)* ): &'a mut ($($t,)*)) -> Self::Field { diff --git a/src/lenses/to.rs b/src/lenses/to.rs index bce8369..d9309dd 100644 --- a/src/lenses/to.rs +++ b/src/lenses/to.rs @@ -1,9 +1,8 @@ -use crate::{lenses::LensView, Optics, OpticsTrait}; +use crate::lenses::{Lens, LensView}; use super::lens::LensInner; pub struct ToInner(Box U>); -impl OpticsTrait for ToInner {} impl LensView for ToInner { type Field = U; @@ -14,17 +13,17 @@ impl LensView for ToInner { } /// Makes a lens that implements `LensView` with the provided function -pub fn to_from_boxed(f: Box U>) -> Optics> { - Optics(ToInner(f)) +pub fn to_from_boxed(f: Box U>) -> Lens> { + Lens(ToInner(f)) } /// Makes a lens that implements `LensView` with the provided function -pub fn to(f: impl Fn(T) -> U + 'static) -> Optics> { - Optics(ToInner(Box::new(f))) +pub fn to(f: impl Fn(T) -> U + 'static) -> Lens> { + Lens(ToInner(Box::new(f))) } -impl Optics> { +impl Lens> { /// Makes a full lens that implements `LensView` and `LensOver` with the provided functions - pub fn make_lens(self, setter: impl Fn(T, U) -> T + 'static) -> Optics> { - Optics(LensInner((self.0).0, Box::new(setter))) + pub fn make_lens(self, setter: impl Fn(T, U) -> T + 'static) -> Lens> { + Lens(LensInner((self.0).0, Box::new(setter))) } } diff --git a/src/lib.rs b/src/lib.rs index 0cbf6c1..616e1f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,5 @@ #![feature(unboxed_closures, fn_traits)] -/// Base trait -pub trait OpticsTrait {} - -/// Wrapper type -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct Optics(pub(crate) T); -impl OpticsTrait for Optics {} - mod combinations; mod fns; pub mod lenses; diff --git a/src/prisms/mod.rs b/src/prisms/mod.rs index 6ae71cf..c89bc36 100644 --- a/src/prisms/mod.rs +++ b/src/prisms/mod.rs @@ -1,6 +1,15 @@ -use crate::{Optics, OpticsTrait}; +mod result; +pub use result::{_Err, _Ok}; -pub trait PrismPreview: OpticsTrait { +mod option; +pub use option::{_None, _Some}; + +/// Wrapper type +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct Prism

(pub(crate) P); + +pub trait PrismPreview { type Field; fn preview(thing: T) -> Option; @@ -9,7 +18,7 @@ pub trait PrismReview: PrismPreview { fn review(thing: Self::Field) -> T; } -impl PrismPreview for Optics

+impl PrismPreview for Prism

where P: PrismPreview, { @@ -20,7 +29,7 @@ where } } -impl PrismReview for Optics

+impl PrismReview for Prism

where P: PrismReview, { @@ -36,12 +45,6 @@ pub fn review>(_prism: P, thing: P::Field) -> T { P::review(thing) } -mod result; -pub use result::{_Err, _Ok}; - -mod option; -pub use option::{_None, _Some}; - #[cfg(test)] mod tests { use super::*; diff --git a/src/prisms/option.rs b/src/prisms/option.rs index ef287ef..16e6436 100644 --- a/src/prisms/option.rs +++ b/src/prisms/option.rs @@ -3,8 +3,8 @@ use super::*; #[derive(Clone, Copy)] pub struct SomeInner; #[allow(non_upper_case_globals)] -pub const _Some: Optics = Optics(SomeInner); -impl OpticsTrait for SomeInner {} +pub const _Some: Prism = Prism(SomeInner); + impl PrismPreview> for SomeInner { type Field = T; @@ -22,8 +22,7 @@ impl PrismReview> for SomeInner { #[derive(Clone, Copy)] pub struct NoneInner; #[allow(non_upper_case_globals)] -pub const _None: Optics = Optics(NoneInner); -impl OpticsTrait for NoneInner {} +pub const _None: Prism = Prism(NoneInner); impl PrismPreview> for NoneInner { type Field = (); diff --git a/src/prisms/result.rs b/src/prisms/result.rs index 061a227..6dd5cdc 100644 --- a/src/prisms/result.rs +++ b/src/prisms/result.rs @@ -3,8 +3,7 @@ use super::*; #[derive(Clone, Copy)] pub struct OkInner; #[allow(non_upper_case_globals)] -pub const _Ok: Optics = Optics(OkInner); -impl OpticsTrait for OkInner {} +pub const _Ok: Prism = Prism(OkInner); impl PrismPreview> for OkInner { type Field = T; @@ -22,9 +21,7 @@ impl PrismReview> for OkInner { #[derive(Clone, Copy)] pub struct ErrInner; #[allow(non_upper_case_globals)] -pub const _Err: Optics = Optics(ErrInner); - -impl OpticsTrait for ErrInner {} +pub const _Err: Prism = Prism(ErrInner); impl PrismPreview> for ErrInner { type Field = E; diff --git a/src/traversals/both.rs b/src/traversals/both.rs index 0a05ecf..11e3308 100644 --- a/src/traversals/both.rs +++ b/src/traversals/both.rs @@ -1,13 +1,9 @@ -use crate::{ - traversals::{TraversalOver, TraversalTraverse}, - Optics, OpticsTrait, -}; +use crate::traversals::{Traversal, TraversalOver, TraversalTraverse}; #[derive(Clone, Copy)] pub struct BothInner; #[allow(non_upper_case_globals)] -pub const both: Optics = Optics(BothInner); -impl OpticsTrait for BothInner {} +pub const both: Traversal = Traversal(BothInner); impl TraversalTraverse<(T, T)> for BothInner { type Field = T; diff --git a/src/traversals/each.rs b/src/traversals/each.rs index 5b26750..98689e9 100644 --- a/src/traversals/each.rs +++ b/src/traversals/each.rs @@ -1,13 +1,9 @@ -use crate::{ - traversals::{TraversalOver, TraversalTraverse}, - Optics, OpticsTrait, -}; +use crate::traversals::{Traversal, TraversalOver, TraversalTraverse}; #[derive(Clone, Copy)] pub struct EachInner; #[allow(non_upper_case_globals)] -pub const each: Optics = Optics(EachInner); -impl OpticsTrait for EachInner {} +pub const each: Traversal = Traversal(EachInner); impl TraversalTraverse> for EachInner { type Field = T; diff --git a/src/traversals/mod.rs b/src/traversals/mod.rs index 753910a..d3cfef8 100644 --- a/src/traversals/mod.rs +++ b/src/traversals/mod.rs @@ -1,19 +1,20 @@ -use crate::{Optics, OpticsTrait}; - mod both; pub use both::both; mod each; pub use each::each; -/// For lenses that allow viewing -pub trait TraversalTraverse: OpticsTrait { +/// Wrapper type +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct Traversal(pub(crate) T); + +pub trait TraversalTraverse { type Field; fn traverse(&self, thing: T) -> Vec; } -/// For lenses that allow setting pub trait TraversalOver: TraversalTraverse { fn over(&self, thing: T, f: F) -> T where @@ -26,7 +27,7 @@ pub trait TraversalOver: TraversalTraverse { Self::over(self, thing, move |_| v.clone()) } } -impl TraversalTraverse for Optics +impl TraversalTraverse for Traversal where L: TraversalTraverse, { @@ -36,7 +37,7 @@ where L::traverse(&self.0, thing) } } -impl TraversalOver for Optics +impl TraversalOver for Traversal where L: TraversalOver, { @@ -48,29 +49,6 @@ where } } -// // every lens is also a traversal -// impl TraversalTraverse for Optics -// where -// L: LensView, -// { -// type Field = L::Field; - -// fn traverse(&self, thing: T) -> Vec { -// vec![L::view(&self.0, thing)] -// } -// } -// impl TraversalOver for Optics -// where -// L: LensOver, -// { -// fn over(&self, thing: T, f: F) -> T -// where -// F: FnMut(Self::Field) -> Self::Field, -// { -// L::over(&self.0, thing, f) -// } -// } - pub fn traverse>(lens: L, thing: T) -> Vec { L::traverse(&lens, thing) } @@ -92,7 +70,7 @@ mod tests { fn traverse_each_works_on_arrays() { let array = [1, 2, 3, 4]; - let res = over(each, array, |v| v + 1); + let res = each(array, |v| v + 1); assert_eq!(res, [2, 3, 4, 5]); } }