use std::borrow::{Borrow, Cow};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use self::graph::Graph;
use crate::borrowed::PreMonoidBorrowed;
use crate::list::{List, ListBorrowed};
use crate::{Monoid, MonoidBorrowed};
#[allow(missing_docs)]
pub trait HomOnce<M: Monoid> {
type Output: Monoid;
fn call_once(self, m: M) -> Self::Output;
}
#[allow(missing_docs)]
pub trait HomMut<M: Monoid>: HomOnce<M> {
fn call_mut(&mut self, m: M) -> Self::Output;
}
#[allow(missing_docs)]
pub trait Hom<M: Monoid>: HomMut<M> {
fn call(&self, m: M) -> Self::Output;
}
#[allow(missing_docs)]
pub trait HomStatic<M: Monoid>: Hom<M> {
fn call_static(m: M) -> Self::Output;
}
pub mod graph {
use super::*;
pub struct Graph<M: PreMonoidBorrowed, H: HomStaticBorrowed<M>> {
pub(super) input: M,
pub(super) output: H::Output,
#[cfg(feature = "graph-track-inconsistency")]
possibly_inconsistent: bool,
}
impl<M: PreMonoidBorrowed + Clone, H: HomStaticBorrowed<M>> Clone for Graph<M, H>
where
H::Output: Clone,
{
fn clone(&self) -> Self {
Self {
input: self.input.clone(),
output: self.output.clone(),
#[cfg(feature = "graph-track-inconsistency")]
possibly_inconsistent: self.possibly_inconsistent,
}
}
}
impl<M: Monoid, H: HomStaticBorrowed<M>> Monoid for Graph<M, H> {
fn ident() -> Self {
Self {
input: M::ident(),
output: H::Output::ident(),
#[cfg(feature = "graph-track-inconsistency")]
possibly_inconsistent: false,
}
}
fn combine(self, rhs: Self) -> Self {
Self {
input: self.input.combine(rhs.input),
output: self.output.combine(rhs.output),
#[cfg(feature = "graph-track-inconsistency")]
possibly_inconsistent: self.possibly_inconsistent || rhs.possibly_inconsistent,
}
}
fn combine_assign(&mut self, rhs: Self) {
self.input.combine_assign(rhs.input);
self.output.combine_assign(rhs.output);
#[cfg(feature = "graph-track-inconsistency")]
{
self.possibly_inconsistent |= rhs.possibly_inconsistent;
}
}
fn combine_assign_to(self, rhs: &mut Self) {
self.input.combine_assign_to(&mut rhs.input);
self.output.combine_assign_to(&mut rhs.output);
#[cfg(feature = "graph-track-inconsistency")]
{
rhs.possibly_inconsistent |= self.possibly_inconsistent;
}
}
}
impl<M: PreMonoidBorrowed, H: HomStaticBorrowed<M>> Graph<M, H> {
pub fn new(input: M) -> Self {
Self {
output: H::call_static_borrowed(&input),
input,
#[cfg(feature = "graph-track-inconsistency")]
possibly_inconsistent: false,
}
}
pub fn into_pair(self) -> (M, H::Output) {
(self.input, self.output)
}
pub fn input(&self) -> &M {
&self.input
}
#[cfg_attr(
feature = "graph-track-inconsistency",
doc = "can use the [`possibly_inconsistent`](Self::possibly_inconsistent) method."
)]
#[cfg_attr(
not(feature = "graph-track-inconsistency"),
doc = "may want to enable the `graph-track-inconsistency` crate feature
to gain access to the `possibly_inconsistent` method."
)]
pub fn input_mut(&mut self) -> GraphInputRefMut<M, H> {
#[cfg(feature = "graph-track-inconsistency")]
{
self.possibly_inconsistent = true;
}
GraphInputRefMut(self)
}
#[cfg(feature = "graph-track-inconsistency")]
pub fn possibly_inconsistent(&self) -> bool {
self.possibly_inconsistent
}
pub fn recalculate_output(&mut self) {
self.output = H::call_static_borrowed(&self.input);
#[cfg(feature = "graph-track-inconsistency")]
{
self.possibly_inconsistent = false;
}
}
pub fn output(&self) -> &H::Output {
&self.output
}
}
pub struct GraphInputRefMut<'a, M: PreMonoidBorrowed, H: HomStaticBorrowed<M>>(
&'a mut Graph<M, H>,
);
impl<M: PreMonoidBorrowed, H: HomStaticBorrowed<M>> Deref for GraphInputRefMut<'_, M, H> {
type Target = M;
fn deref(&self) -> &Self::Target {
&self.0.input
}
}
impl<M: PreMonoidBorrowed, H: HomStaticBorrowed<M>> DerefMut for GraphInputRefMut<'_, M, H> {
fn deref_mut(&mut self) -> &mut M {
&mut self.0.input
}
}
impl<M: PreMonoidBorrowed, H: HomStaticBorrowed<M>> Drop for GraphInputRefMut<'_, M, H> {
fn drop(&mut self) {
self.0.recalculate_output();
}
}
}
#[allow(missing_docs)]
pub trait HomOnceBorrowed<M: ?Sized + PreMonoidBorrowed> {
type Output: Monoid;
fn call_once_borrowed(self, m: &M) -> Self::Output;
}
#[allow(missing_docs)]
pub trait HomMutBorrowed<M: ?Sized + PreMonoidBorrowed>: HomOnceBorrowed<M> {
fn call_mut_borrowed(&mut self, m: &M) -> Self::Output;
}
#[allow(missing_docs)]
pub trait HomBorrowed<M: ?Sized + PreMonoidBorrowed>: HomMutBorrowed<M> {
fn call_borrowed(&self, m: &M) -> Self::Output;
}
#[allow(missing_docs)]
pub trait HomStaticBorrowed<M: ?Sized + PreMonoidBorrowed>: HomBorrowed<M> {
fn call_static_borrowed(m: &M) -> Self::Output;
}
#[macro_export]
macro_rules! impl_all_monoid_hom {
($(#[doc = $($doc:tt)*])*
impl$([$($gen:tt)*])? HomMut for $T:ty
$(where [$($where:tt)*])? {
$(#[$attr:meta])*
fn call_mut(&mut $self:ident, $m:ident: $inp:ty) -> $O:ty $body:block
}) => {
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomOnce<$inp> for $T
$(where $($where)*)? {
type Output = $O;
#[inline]
fn call_once(mut self, $m: $inp) -> $O {
$crate::hom::HomMut::call_mut(&mut self, $m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomMut<$inp> for $T
$(where $($where)*)? {
$(#[$attr])*
fn call_mut(&mut $self, $m: $inp) -> $O $body
}
};
($(#[doc = $($doc:tt)*])*
impl$([$($gen:tt)*])? Hom for $T:ty
$(where [$($where:tt)*])? {
$(#[$attr:meta])*
fn call(&$self:ident, $m:ident: $inp:ty) -> $O:ty $body:block
}) => {
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomOnce<$inp> for $T
$(where $($where)*)? {
type Output = $O;
#[inline]
fn call_once(self, $m: $inp) -> $O {
$crate::hom::Hom::call(&self, $m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomMut<$inp> for $T
$(where $($where)*)? {
#[inline]
fn call_mut(&mut self, $m: $inp) -> $O {
$crate::hom::Hom::call(&*self, $m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::Hom<$inp> for $T
$(where $($where)*)? {
$(#[$attr])*
fn call(&$self, $m: $inp) -> $O $body
}
};
($(#[doc = $($doc:tt)*])*
impl$([$($gen:tt)*])? HomStatic for $T:ty
$(where [$($where:tt)*])? {
$(#[$attr:meta])*
fn call_static($m:ident: $inp:ty) -> $O:ty $body:block
}) => {
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomOnce<$inp> for $T
$(where $($where)*)? {
type Output = $O;
#[inline]
fn call_once(self, $m: $inp) -> $O {
<Self as $crate::hom::HomStatic<$inp>>::call_static($m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomMut<$inp> for $T
$(where $($where)*)? {
#[inline]
fn call_mut(&mut self, $m: $inp) -> $O {
<Self as $crate::hom::HomStatic<$inp>>::call_static($m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::Hom<$inp> for $T
$(where $($where)*)? {
#[inline]
fn call(&self, $m: $inp) -> $O {
<Self as $crate::hom::HomStatic<$inp>>::call_static($m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomStatic<$inp> for $T
$(where $($where)*)? {
$(#[$attr])*
fn call_static($m: $inp) -> $O $body
}
};
($(#[doc = $($doc:tt)*])*
impl$([$($gen:tt)*])? HomMutBorrowed for $T:ty
$(where [$($where:tt)*])? {
$(#[$attr:meta])*
fn call_mut_borrowed(&mut $self:ident, $m:ident: &$inp:ty) -> $O:ty $body:block
}) => {
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomOnceBorrowed<$inp> for $T
$(where $($where)*)? {
type Output = $O;
#[inline]
fn call_once_borrowed(mut self, $m: &$inp) -> $O {
$crate::hom::HomMutBorrowed::call_mut_borrowed(&mut self, $m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomMutBorrowed<$inp> for $T
$(where $($where)*)? {
$(#[$attr])*
fn call_mut_borrowed(&mut $self, $m: &$inp) -> $O $body
}
};
($(#[doc = $($doc:tt)*])*
impl$([$($gen:tt)*])? HomBorrowed for $T:ty
$(where [$($where:tt)*])? {
$(#[$attr:meta])*
fn call_borrowed(&$self:ident, $m:ident: &$inp:ty) -> $O:ty $body:block
}) => {
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomOnceBorrowed<$inp> for $T
$(where $($where)*)? {
type Output = $O;
#[inline]
fn call_once_borrowed(self, $m: &$inp) -> $O {
$crate::hom::HomBorrowed::call_borrowed(&self, $m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomMutBorrowed<$inp> for $T
$(where $($where)*)? {
#[inline]
fn call_mut_borrowed(&mut self, $m: &$inp) -> $O {
$crate::hom::HomBorrowed::call_borrowed(&*self, $m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomBorrowed<$inp> for $T
$(where $($where)*)? {
$(#[$attr])*
fn call_borrowed(&$self, $m: &$inp) -> $O $body
}
};
($(#[doc = $($doc:tt)*])*
impl$([$($gen:tt)*])? HomStaticBorrowed for $T:ty
$(where [$($where:tt)*])? {
$(#[$attr:meta])*
fn call_static_borrowed($m:ident: &$inp:ty) -> $O:ty $body:block
}) => {
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomOnceBorrowed<$inp> for $T
$(where $($where)*)? {
type Output = $O;
#[inline]
fn call_once_borrowed(self, $m: &$inp) -> $O {
<Self as $crate::hom::HomStaticBorrowed<$inp>>::call_static_borrowed($m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomMutBorrowed<$inp> for $T
$(where $($where)*)? {
#[inline]
fn call_mut_borrowed(&mut self, $m: &$inp) -> $O {
<Self as $crate::hom::HomStaticBorrowed<$inp>>::call_static_borrowed($m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomBorrowed<$inp> for $T
$(where $($where)*)? {
#[inline]
fn call_borrowed(&self, $m: &$inp) -> $O {
<Self as $crate::hom::HomStaticBorrowed<$inp>>::call_static_borrowed($m)
}
}
$(#[doc = $($doc)*])*
impl$(<$($gen)*>)? $crate::hom::HomStaticBorrowed<$inp> for $T
$(where $($where)*)? {
$(#[$attr])*
fn call_static_borrowed($m: &$inp) -> $O $body
}
};
}
pub use crate::impl_all_monoid_hom;
impl_all_monoid_hom!(impl['a, M: Monoid, H: HomMut<M>] HomMut for &'a mut H {
#[inline]
fn call_mut(&mut self, m: M) -> H::Output {
(*self).call_mut(m)
}
});
impl_all_monoid_hom!(impl['a, M: Monoid, H: Hom<M>] Hom for &'a H {
#[inline]
fn call(&self, m: M) -> H::Output {
(*self).call(m)
}
});
impl_all_monoid_hom!(impl['a, M1: Monoid, M2: Monoid] HomMut for Box<dyn 'a + HomMut<M1, Output = M2>> {
#[inline]
fn call_mut(&mut self, m: M1) -> M2 {
(**self).call_mut(m)
}
});
impl_all_monoid_hom!(impl['a, M1: Monoid, M2: Monoid] Hom for Box<dyn 'a + Hom<M1, Output = M2>> {
#[inline]
fn call(&self, m: M1) -> M2 {
(**self).call(m)
}
});
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Id;
impl_all_monoid_hom!(impl[M: Monoid] HomStatic for Id {
#[inline]
fn call_static(m: M) -> M {
m
}
});
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LCombine<M>(pub M);
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RCombine<M>(pub M);
impl<M: Monoid> HomOnce<M> for LCombine<M> {
type Output = M;
#[inline]
fn call_once(self, m: M) -> Self::Output {
self.0.combine(m)
}
}
impl<M: Monoid> HomOnce<M> for RCombine<M> {
type Output = M;
#[inline]
fn call_once(self, m: M) -> Self::Output {
m.combine(self.0)
}
}
impl<M: Monoid + Clone> HomMut<M> for LCombine<M> {
#[inline]
fn call_mut(&mut self, m: M) -> Self::Output {
self.0.clone().combine(m)
}
}
impl<M: Monoid + Clone> HomMut<M> for RCombine<M> {
#[inline]
fn call_mut(&mut self, m: M) -> Self::Output {
m.combine(self.0.clone())
}
}
impl<M: Monoid + Clone> Hom<M> for LCombine<M> {
#[inline]
fn call(&self, m: M) -> Self::Output {
self.0.clone().combine(m)
}
}
impl<M: Monoid + Clone> Hom<M> for RCombine<M> {
#[inline]
fn call(&self, m: M) -> Self::Output {
m.combine(self.0.clone())
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LCombineRef<'a, M: ?Sized>(pub &'a M);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RCombineRef<'a, M: ?Sized>(pub &'a M);
impl<M: ?Sized> Copy for LCombineRef<'_, M> {}
impl<M: ?Sized> Copy for RCombineRef<'_, M> {}
impl<M: ?Sized> Clone for LCombineRef<'_, M> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<M: ?Sized> Clone for RCombineRef<'_, M> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl_all_monoid_hom!(impl['a, M: ?Sized + MonoidBorrowed] Hom for LCombineRef<'a, M> {
#[inline]
fn call(&self, m: M::MonoidOwned) -> M::MonoidOwned {
self.0.combine_left_borrowed(m)
}
});
impl_all_monoid_hom!(impl['a, M: ?Sized + MonoidBorrowed] HomBorrowed for LCombineRef<'a, M> {
#[inline]
fn call_borrowed(&self, m: &M) -> M::MonoidOwned {
self.0.combine_borrowed(m)
}
});
impl_all_monoid_hom!(impl['a, M: ?Sized + MonoidBorrowed] Hom for RCombineRef<'a, M> {
#[inline]
fn call(&self, m: M::MonoidOwned) -> M::MonoidOwned {
M::combine_right_borrowed(m, self.0)
}
});
impl_all_monoid_hom!(impl['a, M: ?Sized + MonoidBorrowed] HomBorrowed for RCombineRef<'a, M> {
#[inline]
fn call_borrowed(&self, m: &M) -> M::MonoidOwned {
m.combine_borrowed(self.0)
}
});
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Chain<H1, H2>(pub H1, pub H2);
pub type Compose<H2, H1> = Chain<H1, H2>;
impl<M1: Monoid, M2: Monoid, M3: Monoid, H1, H2> HomOnce<M1> for Chain<H1, H2>
where
H1: HomOnce<M1, Output = M2>,
H2: HomOnce<M2, Output = M3>,
{
type Output = M3;
fn call_once(self, m: M1) -> Self::Output {
self.1.call_once(self.0.call_once(m))
}
}
impl<M1: Monoid, M2: Monoid, M3: Monoid, H1, H2> HomMut<M1> for Chain<H1, H2>
where
H1: HomMut<M1, Output = M2>,
H2: HomMut<M2, Output = M3>,
{
fn call_mut(&mut self, m: M1) -> Self::Output {
self.1.call_mut(self.0.call_mut(m))
}
}
impl<M1: Monoid, M2: Monoid, M3: Monoid, H1, H2> Hom<M1> for Chain<H1, H2>
where
H1: Hom<M1, Output = M2>,
H2: Hom<M2, Output = M3>,
{
fn call(&self, m: M1) -> Self::Output {
self.1.call(self.0.call(m))
}
}
impl<M1: Monoid, M2: Monoid, M3: Monoid, H1, H2> HomStatic<M1> for Chain<H1, H2>
where
H1: HomStatic<M1, Output = M2>,
H2: HomStatic<M2, Output = M3>,
{
fn call_static(m: M1) -> Self::Output {
H2::call_static(H1::call_static(m))
}
}
impl<M1: ?Sized + PreMonoidBorrowed, M2: Monoid, M3: Monoid, H1, H2> HomOnceBorrowed<M1>
for Chain<H1, H2>
where
H1: HomOnceBorrowed<M1, Output = M2>,
H2: HomOnce<M2, Output = M3>,
{
type Output = M3;
fn call_once_borrowed(self, m: &M1) -> Self::Output {
self.1.call_once(self.0.call_once_borrowed(m))
}
}
impl<M1: ?Sized + PreMonoidBorrowed, M2: Monoid, M3: Monoid, H1, H2> HomMutBorrowed<M1>
for Chain<H1, H2>
where
H1: HomMutBorrowed<M1, Output = M2>,
H2: HomMut<M2, Output = M3>,
{
fn call_mut_borrowed(&mut self, m: &M1) -> Self::Output {
self.1.call_mut(self.0.call_mut_borrowed(m))
}
}
impl<M1: ?Sized + PreMonoidBorrowed, M2: Monoid, M3: Monoid, H1, H2> HomBorrowed<M1>
for Chain<H1, H2>
where
H1: HomBorrowed<M1, Output = M2>,
H2: Hom<M2, Output = M3>,
{
fn call_borrowed(&self, m: &M1) -> Self::Output {
self.1.call(self.0.call_borrowed(m))
}
}
impl<M1: ?Sized + PreMonoidBorrowed, M2: Monoid, M3: Monoid, H1, H2> HomStaticBorrowed<M1>
for Chain<H1, H2>
where
H1: HomStaticBorrowed<M1, Output = M2>,
H2: HomStatic<M2, Output = M3>,
{
fn call_static_borrowed(m: &M1) -> Self::Output {
H2::call_static(H1::call_static_borrowed(m))
}
}
impl<'a, M: 'a + Monoid> Monoid for Box<dyn 'a + HomMut<M, Output = M>> {
fn ident() -> Self {
Box::new(Id)
}
fn combine(self, rhs: Self) -> Self {
Box::new(Chain(self, rhs))
}
}
impl<'a, M: 'a + Monoid> Monoid for Box<dyn 'a + Hom<M, Output = M>> {
fn ident() -> Self {
Box::new(Id)
}
fn combine(self, rhs: Self) -> Self {
Box::new(Chain(self, rhs))
}
}
pub struct GetIdent<M: Monoid>(PhantomData<M>);
impl_all_monoid_hom! {
impl[M: Monoid] HomStatic for GetIdent<M> {
#[inline]
fn call_static(_m: ()) -> M {
M::ident()
}
}
}
impl_all_monoid_hom! {
impl[M: Monoid] HomStaticBorrowed for GetIdent<M> {
#[inline]
fn call_static_borrowed(_m: &()) -> M {
M::ident()
}
}
}
impl_all_monoid_hom! {
impl[M: Monoid] HomStatic for () {
#[inline]
fn call_static(_m: M) -> () {}
}
}
impl_all_monoid_hom! {
impl[M: PreMonoidBorrowed] HomStaticBorrowed for () {
#[inline]
fn call_static_borrowed(_m: &M) -> () {}
}
}
impl<M1: Monoid, M2: Monoid, H1, H2> HomOnce<(M1, M2)> for (H1, H2)
where
H1: HomOnce<M1>,
H2: HomOnce<M2>,
{
type Output = (H1::Output, H2::Output);
#[inline]
fn call_once(self, (m1, m2): (M1, M2)) -> Self::Output {
(self.0.call_once(m1), self.1.call_once(m2))
}
}
impl<M1: Monoid, M2: Monoid, H1, H2> HomMut<(M1, M2)> for (H1, H2)
where
H1: HomMut<M1>,
H2: HomMut<M2>,
{
#[inline]
fn call_mut(&mut self, (m1, m2): (M1, M2)) -> Self::Output {
(self.0.call_mut(m1), self.1.call_mut(m2))
}
}
impl<M1: Monoid, M2: Monoid, H1, H2> Hom<(M1, M2)> for (H1, H2)
where
H1: Hom<M1>,
H2: Hom<M2>,
{
#[inline]
fn call(&self, (m1, m2): (M1, M2)) -> Self::Output {
(self.0.call(m1), self.1.call(m2))
}
}
impl<M1: Monoid, M2: Monoid, H1, H2> HomStatic<(M1, M2)> for (H1, H2)
where
H1: HomStatic<M1>,
H2: HomStatic<M2>,
{
#[inline]
fn call_static((m1, m2): (M1, M2)) -> Self::Output {
(H1::call_static(m1), H2::call_static(m2))
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ToOwned;
impl_all_monoid_hom!(impl[M: ?Sized + MonoidBorrowed + std::borrow::ToOwned<Owned = M::MonoidOwned>] HomStaticBorrowed for ToOwned {
#[inline]
fn call_static_borrowed(m: &M) -> M::MonoidOwned {
m.to_owned()
}
});
pub struct CowFromOwned<'a, M>(PhantomData<fn(M::MonoidOwned) -> Cow<'a, M>>)
where
M: 'a
+ ?Sized
+ PreMonoidBorrowed<MonoidOwned: 'a>
+ std::borrow::ToOwned<Owned = M::MonoidOwned>;
impl_all_monoid_hom!(impl['a, M: 'a + ?Sized + MonoidBorrowed<MonoidOwned: 'a> + std::borrow::ToOwned<Owned = M::MonoidOwned>] HomStatic for CowFromOwned<'a, M> {
#[inline]
fn call_static(m: M::MonoidOwned) -> Cow<'a, M> {
Cow::Owned(m)
}
});
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CowIntoOwned<'a, M>(PhantomData<fn(Cow<'a, M>) -> M::MonoidOwned>)
where
M: 'a
+ ?Sized
+ PreMonoidBorrowed<MonoidOwned: 'a>
+ std::borrow::ToOwned<Owned = M::MonoidOwned>;
impl_all_monoid_hom!(impl['a, M: 'a + ?Sized + MonoidBorrowed<MonoidOwned: 'a> + std::borrow::ToOwned<Owned = M::MonoidOwned>] HomStatic for CowIntoOwned<'a, M> {
#[inline]
fn call_static(m: Cow<'a, M>) -> M::MonoidOwned {
m.into_owned()
}
});
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GraphInputClone;
impl_all_monoid_hom!(impl[M: Monoid, H: HomStaticBorrowed<M>] HomStatic for GraphInputClone
where [M: Clone] {
#[inline]
fn call_static(graph: Graph<M, H>) -> M {
graph.input.clone()
}
});
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GraphOutputClone;
impl_all_monoid_hom!(impl[M: Monoid, H: HomStaticBorrowed<M>] HomStatic for GraphOutputClone
where [H::Output: Clone] {
#[inline]
fn call_static(graph: Graph<M, H>) -> H::Output {
graph.output.clone()
}
});
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ListHomFromFn<F>(pub F);
impl_all_monoid_hom!(impl[L: List, M: Monoid, F: FnMut(L::Item) -> M] HomMut for ListHomFromFn<F> {
fn call_mut(&mut self, v: L) -> M {
M::combine_iter(v.into_items().map(&mut self.0))
}
});
impl<L: List, M: Monoid, F: Fn(L::Item) -> M> Hom<L> for ListHomFromFn<F> {
fn call(&self, v: L) -> M {
M::combine_iter(v.into_items().map(&self.0))
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ListIsom<L>(PhantomData<fn() -> L>);
impl_all_monoid_hom!(impl[T, L1: List<Item = T>, L2: List<Item = T>] HomStatic for ListIsom<L2> {
fn call_static(list: L1) -> L2 {
L2::from_items(list.into_items())
}
});
impl_all_monoid_hom!(impl[T, L1: ListBorrowed, L2: List<Item = T>] HomStaticBorrowed for ListIsom<L2>
where [T: Clone, L1::MonoidOwned: List<Item = T>]
{
fn call_static_borrowed(list: &L1) -> L2 {
L2::from_items(list.items().map(|it| it.borrow().clone()))
}
});