use crate::{HKT2Unbound, Morphism, Satisfies};
pub trait Endomorphism<P: HKT2Unbound>: Morphism<P> {
fn iterate_n<T>(arrow: &P::Type<T, T>, x: T, n: usize) -> T
where
T: Satisfies<P::Constraint>,
{
let mut acc = x;
for _ in 0..n {
acc = Self::apply(arrow, acc);
}
acc
}
fn iterate_to_fixpoint<T>(arrow: &P::Type<T, T>, x: T, max_steps: usize) -> (T, bool)
where
T: Satisfies<P::Constraint> + Clone + PartialEq,
{
let mut acc = x;
for _ in 0..max_steps {
let next = Self::apply(arrow, acc.clone());
if next == acc {
return (next, true);
}
acc = next;
}
(acc, false)
}
fn iterate_until<T, Pred>(
arrow: &P::Type<T, T>,
x: T,
mut predicate: Pred,
max_steps: usize,
) -> (T, bool)
where
T: Satisfies<P::Constraint>,
Pred: FnMut(&T) -> bool,
{
let mut acc = x;
if predicate(&acc) {
return (acc, true);
}
for _ in 0..max_steps {
acc = Self::apply(arrow, acc);
if predicate(&acc) {
return (acc, true);
}
}
(acc, false)
}
}
impl<P: HKT2Unbound, M: Morphism<P>> Endomorphism<P> for M {}