add prisms
This commit is contained in:
parent
037440c845
commit
ea617b8789
7 changed files with 291 additions and 104 deletions
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
104
src/lib.rs
104
src/lib.rs
|
@ -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
94
src/prisms/mod.rs
Normal 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
39
src/prisms/option.rs
Normal 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
41
src/prisms/result.rs
Normal 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)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue