make adding lenses be const

main
annieversary 2021-11-12 13:09:23 +00:00
parent ca9d8de37f
commit c3d76f109f
6 changed files with 44 additions and 28 deletions

View File

@ -6,7 +6,9 @@ ergonomic lenses in rust
it does *not* implement the operators, as it's not really a thing we can do in rust
does bringing lenses into rust actually make sense? probably not, but it was fun to implement
you will need nightly for this library to work, as it uses a bunch of unstable features. they're technically not *critical*, but i think not having them reduces the ergonomics too much
does bringing lenses into rust actually make sense? probably not, but it was fun to implement so who can say
## example

View File

@ -3,6 +3,7 @@ use crate::{
prisms::{Prism, PrismPreview},
traversals::{Traversal, TraversalOver, TraversalTraverse},
};
use std::ops::Add;
#[derive(Clone, Copy)]
pub struct Combination<A, B>(A, B);
@ -10,7 +11,7 @@ pub struct Combination<A, B>(A, B);
// additions
// lens + lens
impl<A, B> std::ops::Add<Lens<B>> for Lens<A> {
impl<A, B> const Add<Lens<B>> for Lens<A> {
type Output = Lens<Combination<Lens<A>, Lens<B>>>;
fn add(self, rhs: Lens<B>) -> Self::Output {
@ -18,7 +19,7 @@ impl<A, B> std::ops::Add<Lens<B>> for Lens<A> {
}
}
// prism + prism
impl<A, B> std::ops::Add<Prism<B>> for Prism<A> {
impl<A, B> const Add<Prism<B>> for Prism<A> {
type Output = Prism<Combination<Prism<A>, Prism<B>>>;
fn add(self, rhs: Prism<B>) -> Self::Output {
@ -26,7 +27,7 @@ impl<A, B> std::ops::Add<Prism<B>> for Prism<A> {
}
}
// traversal + traversal
impl<A, B> std::ops::Add<Traversal<B>> for Traversal<A> {
impl<A, B> const Add<Traversal<B>> for Traversal<A> {
type Output = Traversal<Combination<Traversal<A>, Traversal<B>>>;
fn add(self, rhs: Traversal<B>) -> Self::Output {
@ -34,7 +35,7 @@ impl<A, B> std::ops::Add<Traversal<B>> for Traversal<A> {
}
}
// traversal + lens
impl<A, B> std::ops::Add<Lens<B>> for Traversal<A> {
impl<A, B> const Add<Lens<B>> for Traversal<A> {
type Output = Traversal<Combination<Traversal<A>, Traversal<Lens<B>>>>;
fn add(self, rhs: Lens<B>) -> Self::Output {
@ -42,7 +43,7 @@ impl<A, B> std::ops::Add<Lens<B>> for Traversal<A> {
}
}
// lens + traversal
impl<A, B> std::ops::Add<Traversal<B>> for Lens<A> {
impl<A, B> const Add<Traversal<B>> for Lens<A> {
type Output = Traversal<Combination<Traversal<Lens<A>>, Traversal<B>>>;
fn add(self, rhs: Traversal<B>) -> Self::Output {
@ -50,7 +51,7 @@ impl<A, B> std::ops::Add<Traversal<B>> for Lens<A> {
}
}
// traversal + prism
impl<A, B> std::ops::Add<Prism<B>> for Traversal<A> {
impl<A, B> const Add<Prism<B>> for Traversal<A> {
type Output = Traversal<Combination<Traversal<A>, Traversal<Prism<B>>>>;
fn add(self, rhs: Prism<B>) -> Self::Output {
@ -58,7 +59,7 @@ impl<A, B> std::ops::Add<Prism<B>> for Traversal<A> {
}
}
// prism + traversal
impl<A, B> std::ops::Add<Traversal<B>> for Prism<A> {
impl<A, B> const Add<Traversal<B>> for Prism<A> {
type Output = Traversal<Combination<Traversal<Prism<A>>, Traversal<B>>>;
fn add(self, rhs: Traversal<B>) -> Self::Output {
@ -66,7 +67,7 @@ impl<A, B> std::ops::Add<Traversal<B>> for Prism<A> {
}
}
// lens + prism
impl<A, B> std::ops::Add<Prism<B>> for Lens<A> {
impl<A, B> const Add<Prism<B>> for Lens<A> {
type Output = Traversal<Combination<Traversal<Lens<A>>, Traversal<Prism<B>>>>;
fn add(self, rhs: Prism<B>) -> Self::Output {
@ -74,7 +75,7 @@ impl<A, B> std::ops::Add<Prism<B>> for Lens<A> {
}
}
// prism + traversal
impl<A, B> std::ops::Add<Lens<B>> for Prism<A> {
impl<A, B> const Add<Lens<B>> for Prism<A> {
type Output = Traversal<Combination<Traversal<Prism<A>>, Traversal<Lens<B>>>>;
fn add(self, rhs: Lens<B>) -> Self::Output {
@ -321,4 +322,17 @@ mod tests {
let res = t(thing, |v| v + 1);
assert_eq!(res, (Some(2), 2));
}
#[test]
fn can_combine_as_const() {
use crate::lenses::first::_0Inner;
use crate::lenses::Lens;
const LENS: Lens<super::Combination<Lens<_0Inner>, Lens<_0Inner>>> = _0 + _0;
let thing: ((i32, i32), i32) = ((1, 2), 3);
let r: i32 = LENS(thing);
assert_eq!(r, 1);
}
}

View File

@ -1,22 +1,22 @@
mod fields;
pub mod fields;
mod identity;
pub mod identity;
pub use identity::id;
mod first;
pub mod first;
pub use first::_0;
mod second;
pub mod second;
pub use second::_1;
mod third;
pub mod third;
pub use third::_2;
mod fourth;
pub mod fourth;
pub use fourth::_3;
mod fifth;
pub mod fifth;
pub use fifth::_4;
mod to;
pub mod to;
pub use to::{to, to_from_boxed};
mod lens;
pub mod lens;
pub use lens::{lens, lens_from_boxed};
/// Wrapper type

View File

@ -1,4 +1,4 @@
#![feature(unboxed_closures, fn_traits)]
#![feature(unboxed_closures, fn_traits, const_trait_impl)]
pub mod combinations;
mod fns;

View File

@ -1,7 +1,7 @@
mod result;
pub mod result;
pub use result::{_Err, _Ok};
mod option;
pub mod option;
pub use option::{_None, _Some};
/// Wrapper type

View File

@ -1,12 +1,12 @@
mod both;
pub mod both;
pub use both::both;
mod each;
pub mod each;
pub use each::each;
mod head;
pub mod head;
pub use head::_head;
mod tail;
pub mod tail;
pub use tail::_tail;
use crate::{
@ -62,7 +62,7 @@ where
// all lenses are traversals, so we can freely transform them into a traversal
impl<L> Lens<L> {
/// Returns this lens as a traversal
pub fn to_traversal(self) -> Traversal<Lens<L>> {
pub const fn to_traversal(self) -> Traversal<Lens<L>> {
Traversal(self)
}
}
@ -98,7 +98,7 @@ where
// all prisms are traversals, so we can freely transform them into a traversal
impl<L> Prism<L> {
/// Returns this lens as a traversal
pub fn to_traversal(self) -> Traversal<Prism<L>> {
pub const fn to_traversal(self) -> Traversal<Prism<L>> {
Traversal(self)
}
}