use crate::Arrow;
pub trait EndoArrow<S>: Arrow<In = S, Out = S> {
#[inline]
fn iterate_n(&self, initial: S, n: usize) -> S {
let mut state = initial;
for _ in 0..n {
state = self.run(state);
}
state
}
#[inline]
fn iterate_to_fixpoint(&self, initial: S, max_steps: usize) -> (S, bool)
where
S: Clone + PartialEq,
{
let mut state = initial;
for _ in 0..max_steps {
let next = self.run(state.clone());
if next == state {
return (next, true);
}
state = next;
}
(state, false)
}
#[inline]
fn iterate_until<P>(&self, initial: S, mut predicate: P, max_steps: usize) -> (S, bool)
where
P: FnMut(&S) -> bool,
{
let mut state = initial;
if predicate(&state) {
return (state, true);
}
for _ in 0..max_steps {
state = self.run(state);
if predicate(&state) {
return (state, true);
}
}
(state, false)
}
}
impl<S, A: Arrow<In = S, Out = S>> EndoArrow<S> for A {}