use crate::{just_alternative, prelude::*};
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, QuickCheck)]
pub struct List<A>(Vec<A>);
#[macro_export]
macro_rules! list {
($a:literal..$b:expr)=>{($a..$b).collect::<$crate::prelude::List<_>>()};
({$a:expr}..$b:expr)=>{($a..$b).collect::<$crate::prelude::List<_>>()};
($($e:expr),*) => {
<$crate::prelude::List<_> as From<Vec<_>>>::from(vec![$($e),*])
};
}
pub use list;
#[allow(clippy::module_name_repetitions)]
#[macro_export]
macro_rules! lazy_list {
($($e:expr),*) => {
<$crate::prelude::List<_> as From<Vec<_>>>::from(vec![$(|| $e),*])
};
}
#[allow(clippy::module_name_repetitions)]
pub use lazy_list;
impl<A> From<Vec<A>> for List<A> {
#[inline(always)]
fn from(value: Vec<A>) -> Self {
Self(value)
}
}
impl<T> From<List<T>> for Vec<T> {
#[inline(always)]
fn from(value: List<T>) -> Self {
value.0
}
}
impl<A> List<A> {
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline(always)]
pub fn contains(&self, a: &A) -> bool
where
A: PartialEq,
{
self.0.contains(a)
}
#[inline(always)]
pub fn starts_with(&self, needle: &[A]) -> bool
where
A: PartialEq,
{
self.0.starts_with(needle)
}
#[inline(always)]
pub fn ends_with(&self, needle: &[A]) -> bool
where
A: PartialEq,
{
self.0.ends_with(needle)
}
#[inline(always)]
#[must_use]
pub fn capacity(&self) -> usize {
self.0.capacity()
}
#[inline(always)]
pub fn reserve(&mut self, additional: usize) {
self.0.reserve(additional);
}
#[inline(always)]
pub fn reserve_exact(&mut self, additional: usize) {
self.0.reserve_exact(additional);
}
#[inline(always)]
pub fn truncate(&mut self, n: usize) {
self.0.truncate(n);
}
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline(always)]
pub fn insert(&mut self, index: usize, element: A) {
self.0.insert(index, element);
}
#[inline(always)]
pub fn remove(&mut self, index: usize) -> A {
self.0.remove(index)
}
#[inline(always)]
pub fn swap_remove(&mut self, index: usize) -> A {
self.0.swap_remove(index)
}
#[inline(always)]
pub fn retain<F: for<'a> core::ops::FnMut(&'a A) -> bool>(&mut self, f: F) {
self.0.retain(f);
}
#[inline(always)]
pub fn push(&mut self, a: A) {
self.0.push(a);
}
#[inline(always)]
pub fn pop(&mut self) -> Maybe<A> {
self.0.pop().into()
}
#[inline(always)]
pub fn append(&mut self, other: &mut Self) {
self.0.append(&mut other.0);
}
}
impl<A> IntoIterator for List<A> {
type Item = A;
type IntoIter = <Vec<A> as IntoIterator>::IntoIter;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<A> FromIterator<A> for List<A> {
#[inline(always)]
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
Self(Vec::from_iter(iter))
}
}
impl<A> core::ops::AddAssign for List<A> {
#[inline(always)]
fn add_assign(&mut self, mut rhs: Self) {
self.append(&mut rhs);
}
}
monad! {
List<A>:
fn consume(b) {
list![b]
}
fn bind(self, f) {
List(self.0.bind(move |a| f(a).0))
}
}
just_alternative! {
List<A>:
fn empty() {
list![]
}
fn either(self, make_other) {
self.0.append(&mut make_other().0);
self
}
}
fold! {
List<A>:
type Item = A;
}
mod list_monoid_impl {
#![allow(
clippy::arithmetic_side_effects,
clippy::missing_docs_in_private_items,
clippy::missing_trait_methods,
clippy::wildcard_imports
)]
use super::*;
impl<A> Monoid for List<A> {
#[inline(always)]
#[must_use]
fn unit() -> Self {
<Self as From<Vec<_>>>::from(Vec::new())
}
#[inline(always)]
#[must_use]
fn combine(mut self, mut other: Self) -> Self {
self.append(&mut other);
self
}
}
impl<A> core::ops::Add<Self> for List<A> {
type Output = Self;
#[inline(always)]
#[must_use]
fn add(self, other: Self) -> Self {
self.combine(other)
}
}
crate::test_monoid! { List<u64> }
}