,
+ 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/prisms/mod.rs b/src/prisms/mod.rs
index c89bc36..536ac1c 100644
--- a/src/prisms/mod.rs
+++ b/src/prisms/mod.rs
@@ -12,10 +12,28 @@ pub struct Prism(pub(crate) P);
pub trait PrismPreview {
type Field;
- fn preview(thing: T) -> Option;
-}
-pub trait PrismReview: PrismPreview {
- fn review(thing: Self::Field) -> T;
+ fn preview(&self, thing: T) -> Option;
+ fn review(&self, thing: Self::Field) -> T;
+ // TODO id like for this to not need clone
+ fn over(&self, thing: T, f: F) -> T
+ where
+ F: FnOnce(Self::Field) -> Self::Field,
+ T: Clone,
+ {
+ if let Some(a) = Self::preview(&self, thing.clone()) {
+ Self::review(&self, f(a))
+ } else {
+ thing
+ }
+ }
+
+ fn set(&self, thing: T, v: Self::Field) -> T
+ where
+ T: Clone,
+ Self::Field: Clone,
+ {
+ Self::over(self, thing, move |_| v.clone())
+ }
}
impl PrismPreview for Prism
@@ -24,25 +42,27 @@ where
{
type Field = P::Field;
- fn preview(thing: T) -> Option {
- P::preview(thing)
+ fn preview(&self, thing: T) -> Option {
+ P::preview(&self.0, thing)
+ }
+
+ fn review(&self, thing: Self::Field) -> T {
+ P::review(&self.0, thing)
}
}
-impl PrismReview for Prism
-where
- P: PrismReview,
-{
- fn review(thing: Self::Field) -> T {
- P::review(thing)
- }
+pub fn preview>(prism: P, thing: T) -> Option {
+ P::preview(&prism, thing)
}
-
-pub fn preview>(_prism: P, thing: T) -> Option {
- P::preview(thing)
+pub fn review>(prism: P, thing: P::Field) -> T {
+ P::review(&prism, thing)
}
-pub fn review>(_prism: P, thing: P::Field) -> T {
- P::review(thing)
+pub fn over>(
+ prism: P,
+ thing: T,
+ f: impl FnOnce(P::Field) -> P::Field,
+) -> T {
+ P::over(&prism, thing, f)
}
#[cfg(test)]
@@ -52,13 +72,13 @@ mod tests {
#[test]
fn preview_result() {
let a: Result = Ok(3);
- assert_eq!(preview(_Ok, a), Some(3));
+ assert_eq!(_Ok(a), Some(3));
let a: Result = Err(3);
assert_eq!(preview(_Ok, a), None);
let a: Result = Ok(3);
- assert_eq!(preview(_Err, a), None);
+ assert_eq!(_Err(a), None);
let a: Result = Err(3);
assert_eq!(preview(_Err, a), Some(3));
@@ -67,7 +87,7 @@ mod tests {
#[test]
fn preview_option() {
let a = Some(3);
- assert_eq!(preview(_Some, a), Some(3));
+ assert_eq!(_Some(a), Some(3));
let a = Some(3);
assert_eq!(preview(_None, a), Some(()));
@@ -90,4 +110,11 @@ mod tests {
assert_eq!(review(_Some, 3), Some(3));
assert_eq!(review(_None, ()), None::<()>);
}
+
+ #[test]
+ fn over_option() {
+ assert_eq!(over(_Some, Some(3), |v| v + 1), Some(4));
+ assert_eq!(_Some(Some(3), |v| v + 1), Some(4));
+ assert_eq!(over(_None, None, |_v: ()| ()), None::<()>);
+ }
}
diff --git a/src/prisms/option.rs b/src/prisms/option.rs
index 16e6436..e856542 100644
--- a/src/prisms/option.rs
+++ b/src/prisms/option.rs
@@ -8,13 +8,11 @@ pub const _Some: Prism = Prism(SomeInner);
impl PrismPreview