bad-optics/src/lib.rs

178 lines
3.4 KiB
Rust
Raw Normal View History

2021-11-05 14:22:59 +00:00
#![feature(unboxed_closures, fn_traits)]
2021-11-05 13:27:34 +00:00
/// Base trait
pub trait LensTrait {}
/// For lenses that allow viewing
pub trait LensView<T>: LensTrait {
2021-11-05 10:12:03 +00:00
type Field;
fn view(thing: T) -> Self::Field;
}
2021-11-05 13:27:34 +00:00
/// For lenses that allow setting
2021-11-05 10:12:03 +00:00
pub trait LensOver<T>: LensView<T> {
fn over<F>(thing: T, f: F) -> T
where
F: FnOnce(Self::Field) -> Self::Field;
2021-11-05 11:03:17 +00:00
fn set(thing: T, v: Self::Field) -> T {
Self::over(thing, |_| v)
2021-11-05 11:03:17 +00:00
}
2021-11-05 10:12:03 +00:00
}
2021-11-05 13:27:34 +00:00
/// Wrapper type
2021-11-05 14:22:59 +00:00
#[derive(Clone, Copy)]
2021-11-05 13:27:34 +00:00
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)
}
}
2021-11-05 10:12:03 +00:00
pub fn view<T, L: LensView<T>>(_lens: L, thing: T) -> L::Field {
L::view(thing)
}
2021-11-05 11:03:17 +00:00
pub fn set<T, L: LensOver<T>>(_lens: L, thing: T, v: L::Field) -> T {
L::set(thing, v)
}
pub fn over<T, L: LensOver<T>>(_lens: L, thing: T, f: impl FnOnce(L::Field) -> L::Field) -> T {
2021-11-05 10:12:03 +00:00
L::over(thing, f)
}
2021-11-05 13:27:34 +00:00
// TODO add third_from_tuple, etc
2021-11-05 11:03:17 +00:00
// TODO array traversals
2021-11-05 15:28:34 +00:00
// TODO something for structs
2021-11-05 11:03:17 +00:00
// TODO make over work with changing types
2021-11-05 14:22:59 +00:00
mod combinations;
mod fns;
2021-11-05 10:12:03 +00:00
pub mod lenses;
#[cfg(test)]
mod tests {
2021-11-05 13:27:34 +00:00
use super::{
lenses::{_0, _1},
*,
};
2021-11-05 10:12:03 +00:00
#[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]
2021-11-05 11:03:17 +00:00
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() {
2021-11-05 10:12:03 +00:00
let a = (1, 2);
2021-11-05 12:09:20 +00:00
let a = over(_0, a, |v| v + 1);
2021-11-05 10:12:03 +00:00
assert_eq!(a, (2, 2));
}
2021-11-05 12:09:20 +00:00
#[test]
fn over_first_from_array() {
let a = [1, 2, 3, 4];
2021-11-05 13:27:34 +00:00
let a = over(_0, a, |v| v + 1);
2021-11-05 12:09:20 +00:00
assert_eq!(a, [2, 2, 3, 4]);
}
2021-11-05 13:27:34 +00:00
#[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));
}
2021-11-05 14:22:59 +00:00
#[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);
2021-11-05 15:28:34 +00:00
let res = _0(a);
assert_eq!(res, (1, 2));
2021-11-05 14:22:59 +00:00
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));
}
2021-11-05 10:12:03 +00:00
}