use std::borrow::Borrow;
use std::iter::FusedIterator;
use std::ops::Deref;
use crate::hom::graph::Graph;
use crate::hom::HomStaticBorrowed;
use crate::{Monoid, PreMonoidBorrowed};
pub trait List: Monoid {
#[allow(missing_docs)]
type Item;
fn single(value: Self::Item) -> Self;
fn from_items(iter: impl IntoIterator<Item = Self::Item>) -> Self {
Self::combine_iter(iter.into_iter().map(Self::single))
}
fn push(&mut self, value: Self::Item) {
self.combine_assign(Self::single(value));
}
fn extend(&mut self, iter: impl IntoIterator<Item = Self::Item>) {
self.combine_iter_assign(iter.into_iter().map(Self::single));
}
fn into_items(self) -> impl FusedIterator<Item = Self::Item>;
}
#[allow(clippy::len_without_is_empty)]
pub trait ListBorrowed: PreMonoidBorrowed<MonoidOwned: List> {
type ItemRef<'a>: Borrow<<Self::MonoidOwned as List>::Item>
where
Self: 'a;
fn items(&self) -> impl FusedIterator<Item = Self::ItemRef<'_>>;
fn len(&self) -> usize {
self.items().count()
}
}
impl<L: List + Deref<Target: ListBorrowed<MonoidOwned = L>>> ListBorrowed for L {
type ItemRef<'a> = <L::Target as ListBorrowed>::ItemRef<'a>
where
Self: 'a;
fn items(&self) -> impl FusedIterator<Item = Self::ItemRef<'_>> {
L::Target::items(self)
}
}
pub trait ListExt: List {
#[inline]
fn empty() -> Self {
Self::ident()
}
#[inline]
fn concat(self, rhs: Self) -> Self {
self.combine(rhs)
}
}
impl<L: List> ListExt for L {}
impl<T> List for Vec<T> {
type Item = T;
fn single(value: T) -> Self {
vec![value]
}
fn from_items(iter: impl IntoIterator<Item = T>) -> Self {
<Self as FromIterator<T>>::from_iter(iter)
}
fn into_items(self) -> impl FusedIterator<Item = T> {
<Self as IntoIterator>::into_iter(self)
}
}
impl<T> ListBorrowed for [T] {
type ItemRef<'a> = &'a T
where T: 'a;
fn items(&self) -> impl FusedIterator<Item = Self::ItemRef<'_>> {
<[T]>::iter(self)
}
fn len(&self) -> usize {
<Self>::len(self)
}
}
impl List for String {
type Item = char;
fn single(value: char) -> Self {
value.into()
}
fn from_items(iter: impl IntoIterator<Item = char>) -> Self {
<Self as FromIterator<char>>::from_iter(iter)
}
fn into_items(self) -> impl FusedIterator<Item = char> {
IntoIterator::into_iter(self.chars().collect::<Vec<_>>())
}
}
impl ListBorrowed for str {
type ItemRef<'a> = char;
fn items(&self) -> impl FusedIterator<Item = Self::ItemRef<'_>> {
self.chars()
}
}
impl<L: List, H: HomStaticBorrowed<L>> Graph<L, H> {
pub fn push_input(&mut self, input: L::Item) {
self.input_mut().push(input);
}
}