src/instance.rs

branch
dev
changeset 133
2b13f8a0c8ba
parent 88
086a59b3a2b4
child 134
d65377920b00
child 136
22fd33834ab7
child 150
c4e394a9c84c
--- a/src/instance.rs	Mon May 12 19:30:41 2025 -0500
+++ b/src/instance.rs	Mon May 12 20:40:14 2025 -0500
@@ -25,7 +25,10 @@
 
 impl<'b, X> MyCow<'b, X> {
     #[inline]
-    pub fn into_owned(self) -> X where X : Clone {
+    pub fn into_owned(self) -> X
+    where
+        X: Clone,
+    {
         match self {
             EitherDecomp::Owned(x) => x,
             EitherDecomp::Borrowed(x) => x.clone(),
@@ -34,9 +37,9 @@
 }
 
 /// Trait for abitrary mathematical spaces.
-pub trait Space : Instance<Self, Self::Decomp> {
+pub trait Space: Instance<Self, Self::Decomp> {
     /// Default decomposition for the space
-    type Decomp : Decomposition<Self>;
+    type Decomp: Decomposition<Self>;
 }
 
 #[macro_export]
@@ -58,17 +61,21 @@
                   f32 f64);
 
 /// Marker type for decompositions to be used with [`Instance`].
-pub trait Decomposition<X : Space> : Sized {
+pub trait Decomposition<X: Space>: Sized {
     /// Possibly owned form of the decomposition
-    type Decomposition<'b> : Instance<X, Self> where X : 'b;
+    type Decomposition<'b>: Instance<X, Self>
+    where
+        X: 'b;
     /// Unlikely owned form of the decomposition.
     /// Type for a lightweight intermediate conversion that does not own the original variable.
     /// Usually this is just a reference, but may also be a lightweight structure that
     /// contains references; see the implementation for [`crate::direct_product::Pair`].
-    type Reference<'b> : Instance<X, Self> + Copy where X : 'b;
+    type Reference<'b>: Instance<X, Self> + Copy
+    where
+        X: 'b;
 
     /// Left the lightweight reference type into a full decomposition type.
-    fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b>;
+    fn lift<'b>(r: Self::Reference<'b>) -> Self::Decomposition<'b>;
 }
 
 /// Most common [`Decomposition`] (into `Either<X, &'b X>`) that allows working with owned
@@ -76,12 +83,18 @@
 #[derive(Copy, Clone, Debug)]
 pub struct BasicDecomposition;
 
-impl<X : Space + Clone> Decomposition<X> for BasicDecomposition {
-    type Decomposition<'b> = MyCow<'b, X> where X : 'b;
-    type Reference<'b> = &'b X where X : 'b;
+impl<X: Space + Clone> Decomposition<X> for BasicDecomposition {
+    type Decomposition<'b>
+        = MyCow<'b, X>
+    where
+        X: 'b;
+    type Reference<'b>
+        = &'b X
+    where
+        X: 'b;
 
     #[inline]
-    fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b> {
+    fn lift<'b>(r: Self::Reference<'b>) -> Self::Decomposition<'b> {
         MyCow::Borrowed(r)
     }
 }
@@ -91,13 +104,23 @@
 /// generalises [`std::borrow::ToOwned`], [`std::borrow::Borrow`], and [`std::borrow::Cow`].
 ///
 /// This is used, for example, by [`crate::mapping::Mapping::apply`].
-pub trait Instance<X : Space, D = <X as Space>::Decomp> : Sized where D : Decomposition<X> {
-    /// Decomposes self according to `decomposer`.
-    fn decompose<'b>(self) -> D::Decomposition<'b>
-    where Self : 'b, X : 'b;
-  
-    /// Returns a lightweight instance of `self`.
-    fn ref_instance(&self) -> D::Reference<'_>;
+pub trait Instance<X: Space, D = <X as Space>::Decomp>: Sized
+where
+    D: Decomposition<X>,
+{
+    /// Decomposes self according to `decomposer`, and evaluate `f` on the result.
+    /// Consumes self.
+    fn eval_decompose<'b, R>(self, f: impl FnOnce(D::Decomposition<'b>) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b;
+
+    /// Does a light decomposition of self `decomposer`, and evaluates `f` on the result.
+    /// Does not consume self.
+    fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(D::Reference<'b>) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b;
 
     /// Returns an owned instance of `X`, cloning or converting non-true instances when necessary.
     fn own(self) -> X;
@@ -107,16 +130,21 @@
     /// Returns an owned instance or reference to `X`, converting non-true instances when necessary.
     ///
     /// Default implementation uses [`Self::own`]. Consumes the input.
-    fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b {
+    fn cow<'b>(self) -> MyCow<'b, X>
+    where
+        Self: 'b,
+    {
         MyCow::Owned(self.own())
     }
-    
+
     #[inline]
     /// Evaluates `f` on a reference to self.
     ///
     /// Default implementation uses [`Self::cow`]. Consumes the input.
-    fn eval<'b, R>(self, f : impl FnOnce(&X) -> R) -> R
-    where X : 'b, Self : 'b
+    fn eval<'b, R>(self, f: impl FnOnce(&X) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
     {
         f(&*self.cow())
     }
@@ -125,12 +153,9 @@
     /// Evaluates `f` or `g` depending on whether a reference or owned value is available.
     ///
     /// Default implementation uses [`Self::cow`]. Consumes the input.
-    fn either<'b, R>(
-        self,
-        f : impl FnOnce(X) -> R,
-        g : impl FnOnce(&X) -> R
-    ) -> R
-    where Self : 'b
+    fn either<'b, R>(self, f: impl FnOnce(X) -> R, g: impl FnOnce(&X) -> R) -> R
+    where
+        Self: 'b,
     {
         match self.cow() {
             EitherDecomp::Owned(x) => f(x),
@@ -139,13 +164,23 @@
     }
 }
 
-
-impl<X : Space + Clone> Instance<X, BasicDecomposition> for X {
+impl<X: Space + Clone> Instance<X, BasicDecomposition> for X {
     #[inline]
-    fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b>
-    where Self : 'b, X : 'b
+    fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
     {
-        MyCow::Owned(self)
+        f(MyCow::Owned(self))
+    }
+
+    #[inline]
+    fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
+    {
+        f(self)
     }
 
     #[inline]
@@ -154,22 +189,31 @@
     }
 
     #[inline]
-    fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b {
+    fn cow<'b>(self) -> MyCow<'b, X>
+    where
+        Self: 'b,
+    {
         MyCow::Owned(self)
     }
+}
+
+impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for &'a X {
+    #[inline]
+    fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
+    {
+        f(MyCow::Borrowed(self))
+    }
 
     #[inline]
-    fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> {
-        self
-    }
-}
-
-impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for &'a X {
-    #[inline]
-    fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b>
-    where Self : 'b, X : 'b
+    fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
     {
-        MyCow::Borrowed(self)
+        f(*self)
     }
 
     #[inline]
@@ -178,22 +222,31 @@
     }
 
     #[inline]
-    fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b {
+    fn cow<'b>(self) -> MyCow<'b, X>
+    where
+        Self: 'b,
+    {
         MyCow::Borrowed(self)
     }
+}
+
+impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for &'a mut X {
+    #[inline]
+    fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
+    {
+        f(EitherDecomp::Borrowed(self))
+    }
 
     #[inline]
-    fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> {
-        *self
-    }
-}
-
-impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for &'a mut X {
-    #[inline]
-    fn  decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b>
-    where Self : 'b, X : 'b
+    fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
     {
-        EitherDecomp::Borrowed(self)
+        f(*self)
     }
 
     #[inline]
@@ -202,81 +255,95 @@
     }
 
     #[inline]
-    fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b, X : Clone {
+    fn cow<'b>(self) -> MyCow<'b, X>
+    where
+        Self: 'b,
+        X: Clone,
+    {
         EitherDecomp::Borrowed(self)
     }
+}
+
+impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for MyCow<'a, X> {
+    #[inline]
+    fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
+    {
+        f(self)
+    }
 
     #[inline]
-    fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> {
-        *self
-    }
-}
-
-impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for MyCow<'a, X> {
-
-    #[inline]
-    fn  decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b>
-    where Self : 'b, X : 'b
+    fn eval_ref_decompose<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R
+    where
+        X: 'b,
+        Self: 'b,
     {
-        self
+        match self {
+            MyCow::Borrowed(a) => f(a),
+            MyCow::Owned(b) => f(&b),
+        }
     }
 
     #[inline]
     fn own(self) -> X {
         match self {
             MyCow::Borrowed(a) => a.own(),
-            MyCow::Owned(b) => b.own()
+            MyCow::Owned(b) => b.own(),
         }
     }
 
     #[inline]
-    fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b {
+    fn cow<'b>(self) -> MyCow<'b, X>
+    where
+        Self: 'b,
+    {
         match self {
             MyCow::Borrowed(a) => a.cow(),
-            MyCow::Owned(b) => b.cow()
-        }
-    }
-
-    #[inline]
-    fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> {
-        match self {
-            MyCow::Borrowed(a) => a,
-            MyCow::Owned(b) => &b,
+            MyCow::Owned(b) => b.cow(),
         }
     }
 }
 
 /// Marker type for mutable decompositions to be used with [`InstanceMut`].
-pub trait DecompositionMut<X : Space> : Sized {
-    type ReferenceMut<'b> : InstanceMut<X, Self> where X : 'b;
+pub trait DecompositionMut<X: Space>: Sized {
+    type ReferenceMut<'b>: InstanceMut<X, Self>
+    where
+        X: 'b;
 }
 
-
 /// Helper trait for functions to work with mutable references.
-pub trait InstanceMut<X : Space , D = <X as Space>::Decomp> : Sized where D : DecompositionMut<X> {
+pub trait InstanceMut<X: Space, D = <X as Space>::Decomp>: Sized
+where
+    D: DecompositionMut<X>,
+{
     /// Returns a mutable decomposition of self.
     fn ref_instance_mut(&mut self) -> D::ReferenceMut<'_>;
 }
 
-impl<X : Space> DecompositionMut<X> for BasicDecomposition {
-    type ReferenceMut<'b> = &'b mut X where X : 'b;
+impl<X: Space> DecompositionMut<X> for BasicDecomposition {
+    type ReferenceMut<'b>
+        = &'b mut X
+    where
+        X: 'b;
 }
 
 /// This impl may seem pointless, but allows throwaway mutable scratch variables
-impl<'a, X : Space> InstanceMut<X, BasicDecomposition> for X {
+impl<'a, X: Space> InstanceMut<X, BasicDecomposition> for X {
     #[inline]
-    fn ref_instance_mut(&mut self)
-        -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_>
-    {
+    fn ref_instance_mut(
+        &mut self,
+    ) -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_> {
         self
     }
 }
 
-impl<'a, X : Space> InstanceMut<X, BasicDecomposition> for &'a mut X {
+impl<'a, X: Space> InstanceMut<X, BasicDecomposition> for &'a mut X {
     #[inline]
-    fn ref_instance_mut(&mut self)
-        -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_>
-    {
+    fn ref_instance_mut(
+        &mut self,
+    ) -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_> {
         self
     }
 }

mercurial