use std::sync::Arc;
use comp_cat_rs::effect::io::Io;
use crate::stage::Stage;
pub trait Filter<I, E> {
fn keep(&self, item: &I) -> Io<E, bool>;
}
pub fn filter_stage<F, I, E>(filter: F) -> Stage<E, Vec<I>, Vec<I>>
where
F: Filter<I, E> + Send + Sync + 'static,
I: Send + 'static,
E: Send + 'static,
{
let filter = Arc::new(filter);
Stage::new(move |items: Vec<I>| {
items.into_iter().fold(Io::pure(Vec::new()), |acc_io, item| {
let f = Arc::clone(&filter);
acc_io.flat_map(move |acc| {
f.keep(&item).map(move |keep| {
if keep {
acc.into_iter().chain(std::iter::once(item)).collect()
} else {
acc
}
})
})
})
})
}