add prisms

This commit is contained in:
annieversary 2021-11-05 19:35:26 +00:00
parent 037440c845
commit ea617b8789
7 changed files with 291 additions and 104 deletions

View file

@ -1,5 +1,6 @@
use crate::{
lenses::{LensOver, LensView},
prisms::PrismPreview,
Optics, OpticsTrait,
};
@ -43,3 +44,15 @@ where
A::over(thing, |b| B::over(b, f))
}
}
impl<A, B, T> PrismPreview<T> for Combination<A, B>
where
A: LensView<T>,
B: PrismPreview<A::Field>,
{
type Field = B::Field;
fn preview(thing: T) -> Option<Self::Field> {
B::preview(A::view(thing))
}
}

View file

@ -57,3 +57,106 @@ pub fn set<T, L: LensOver<T>>(_lens: L, thing: T, v: L::Field) -> T {
pub fn over<T, L: LensOver<T>>(_lens: L, thing: T, f: impl FnOnce(L::Field) -> L::Field) -> T {
L::over(thing, f)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn view_first_from_tuple() {
let a = (1, 2);
assert_eq!(view(_0, a), 1);
let a = (1, 2);
assert_eq!(view(_0, &a), &1);
let mut a = (1, 2);
assert_eq!(view(_0, &mut a), &mut 1);
let a = (1, 2, 3);
assert_eq!(view(_0, a), 1);
let a = (1, 2, 3);
assert_eq!(view(_0, &a), &1);
}
#[test]
fn view_first_from_tuple_mut_works() {
let mut a = (1, 2);
*view(_0, &mut a) += 1;
assert_eq!(a, (2, 2));
}
#[test]
fn set_first_from_tuple() {
let a = (1, 2);
let a = set(_0, a, 3);
assert_eq!(a, (3, 2));
}
#[test]
fn over_first_from_tuple() {
let a = (1, 2);
let a = over(_0, a, |v| v + 1);
assert_eq!(a, (2, 2));
}
#[test]
fn over_first_from_array() {
let a = [1, 2, 3, 4];
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));
}
#[test]
fn call_as_funcs() {
let a = (1, 2);
assert_eq!(_0(a), 1);
let a = (1, 2);
assert_eq!(_0(a, |v| v + 1), (2, 2));
let a = ((1, 2), 3);
let res = _0(a);
assert_eq!(res, (1, 2));
let lens = _0 + _1;
let res = lens(a);
assert_eq!(res, 2);
let res = lens(a, |v| v + 1);
assert_eq!(res, ((1, 3), 3));
}
}

View file

@ -1 +0,0 @@

View file

@ -21,106 +21,4 @@ impl<L: OpticsTrait> OpticsTrait for Optics<L> {}
mod combinations;
mod fns;
pub mod lenses;
#[cfg(test)]
mod tests {
use super::lenses::*;
#[test]
fn view_first_from_tuple() {
let a = (1, 2);
assert_eq!(view(_0, a), 1);
let a = (1, 2);
assert_eq!(view(_0, &a), &1);
let mut a = (1, 2);
assert_eq!(view(_0, &mut a), &mut 1);
let a = (1, 2, 3);
assert_eq!(view(_0, a), 1);
let a = (1, 2, 3);
assert_eq!(view(_0, &a), &1);
}
#[test]
fn view_first_from_tuple_mut_works() {
let mut a = (1, 2);
*view(_0, &mut a) += 1;
assert_eq!(a, (2, 2));
}
#[test]
fn set_first_from_tuple() {
let a = (1, 2);
let a = set(_0, a, 3);
assert_eq!(a, (3, 2));
}
#[test]
fn over_first_from_tuple() {
let a = (1, 2);
let a = over(_0, a, |v| v + 1);
assert_eq!(a, (2, 2));
}
#[test]
fn over_first_from_array() {
let a = [1, 2, 3, 4];
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));
}
#[test]
fn call_as_funcs() {
let a = (1, 2);
assert_eq!(_0(a), 1);
let a = (1, 2);
assert_eq!(_0(a, |v| v + 1), (2, 2));
let a = ((1, 2), 3);
let res = _0(a);
assert_eq!(res, (1, 2));
let lens = _0 + _1;
let res = lens(a);
assert_eq!(res, 2);
let res = lens(a, |v| v + 1);
assert_eq!(res, ((1, 3), 3));
}
}
pub mod prisms;

94
src/prisms/mod.rs Normal file
View file

@ -0,0 +1,94 @@
use crate::{Optics, OpticsTrait};
/// For lenses that allow viewing
pub trait PrismPreview<T>: OpticsTrait {
type Field;
fn preview(thing: T) -> Option<Self::Field>;
}
pub trait PrismReview<T>: PrismPreview<T> {
fn review(thing: Self::Field) -> T;
}
impl<P, T> PrismPreview<T> for Optics<P>
where
P: PrismPreview<T>,
{
type Field = P::Field;
fn preview(thing: T) -> Option<Self::Field> {
P::preview(thing)
}
}
impl<P, T> PrismReview<T> for Optics<P>
where
P: PrismReview<T>,
{
fn review(thing: Self::Field) -> T {
P::review(thing)
}
}
pub fn preview<T, P: PrismPreview<T>>(_prism: P, thing: T) -> Option<P::Field> {
P::preview(thing)
}
pub fn review<T, P: PrismReview<T>>(_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::*;
#[test]
fn preview_result() {
let a: Result<i32, i32> = Ok(3);
assert_eq!(preview(_Ok, a), Some(3));
let a: Result<i32, i32> = Err(3);
assert_eq!(preview(_Ok, a), None);
let a: Result<i32, i32> = Ok(3);
assert_eq!(preview(_Err, a), None);
let a: Result<i32, i32> = Err(3);
assert_eq!(preview(_Err, a), Some(3));
}
#[test]
fn preview_option() {
let a = Some(3);
assert_eq!(preview(_Some, a), Some(3));
let a = Some(3);
assert_eq!(preview(_None, a), Some(()));
let a: Option<i32> = None;
assert_eq!(preview(_Some, a), None);
let a: Option<i32> = None;
assert_eq!(preview(_None, a), Some(()));
}
#[test]
fn review_result() {
assert_eq!(review(_Ok, 3), Ok::<i32, i32>(3));
assert_eq!(review(_Err, 3), Err::<i32, i32>(3));
}
#[test]
fn review_option() {
assert_eq!(review(_Some, 3), Some(3));
assert_eq!(review(_None, ()), None::<()>);
}
#[test]
fn view_combination() {}
}

39
src/prisms/option.rs Normal file
View file

@ -0,0 +1,39 @@
use super::*;
#[derive(Clone, Copy)]
pub struct SomeInner;
#[allow(non_upper_case_globals)]
pub const _Some: Optics<SomeInner> = Optics(SomeInner);
impl OpticsTrait for SomeInner {}
impl<T> PrismPreview<Option<T>> for SomeInner {
type Field = T;
fn preview(thing: Option<T>) -> Option<Self::Field> {
thing
}
}
impl<T> PrismReview<Option<T>> for SomeInner {
fn review(thing: Self::Field) -> Option<T> {
Some(thing)
}
}
#[derive(Clone, Copy)]
pub struct NoneInner;
#[allow(non_upper_case_globals)]
pub const _None: Optics<NoneInner> = Optics(NoneInner);
impl OpticsTrait for NoneInner {}
impl<T> PrismPreview<Option<T>> for NoneInner {
type Field = ();
fn preview(_thing: Option<T>) -> Option<Self::Field> {
Some(())
}
}
impl<T> PrismReview<Option<T>> for NoneInner {
fn review(_thing: Self::Field) -> Option<T> {
None
}
}

41
src/prisms/result.rs Normal file
View file

@ -0,0 +1,41 @@
use super::*;
#[derive(Clone, Copy)]
pub struct OkInner;
#[allow(non_upper_case_globals)]
pub const _Ok: Optics<OkInner> = Optics(OkInner);
impl OpticsTrait for OkInner {}
impl<T, E> PrismPreview<Result<T, E>> for OkInner {
type Field = T;
fn preview(thing: Result<T, E>) -> Option<Self::Field> {
thing.ok()
}
}
impl<T, E> PrismReview<Result<T, E>> for OkInner {
fn review(thing: Self::Field) -> Result<T, E> {
Ok(thing)
}
}
#[derive(Clone, Copy)]
pub struct ErrInner;
#[allow(non_upper_case_globals)]
pub const _Err: Optics<ErrInner> = Optics(ErrInner);
impl OpticsTrait for ErrInner {}
impl<T, E> PrismPreview<Result<T, E>> for ErrInner {
type Field = E;
fn preview(thing: Result<T, E>) -> Option<Self::Field> {
thing.err()
}
}
impl<T, E> PrismReview<Result<T, E>> for ErrInner {
fn review(thing: Self::Field) -> Result<T, E> {
Err(thing)
}
}