cross: list: implement Enumerate operation

This commit is contained in:
2022-08-15 21:25:41 -07:00
parent 1cff95877e
commit a2939a7807

View File

@@ -205,6 +205,59 @@ where
}
}
#[derive(Copy, Clone, Default, PartialEq)]
pub struct Tagged<P: Peano, V> {
inner: V,
_p: P::Unit,
}
impl<P: Peano, V> Tagged<P, V> {
pub fn new(inner: V) -> Self {
Self { inner, _p: P::Unit::default() }
}
pub fn into_inner(self) -> V {
self.inner
}
}
impl<P: Peano, V> core::ops::Deref for Tagged<P, V> {
type Target = V;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<P: Peano, V> core::ops::DerefMut for Tagged<P, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
pub struct EnumerateOp;
impl<L, Next> FoldOp<L, Next> for EnumerateOp
where
L: Meta,
L: Appendable<Tagged<L::Length, Next>>,
{
type Output = Appended<L, Tagged<L::Length, Next>>;
fn feed(&self, prev: L, next: Next) -> Self::Output {
prev.append(Tagged::new(next))
}
}
pub trait Enumerate {
type Output;
fn enumerate(self) -> Self::Output;
}
impl<L> Enumerate for L
where
L: Fold<EnumerateOp, Empty>
{
type Output = L::Output;
fn enumerate(self) -> Self::Output {
self.fold(EnumerateOp, Empty::default())
}
}
#[cfg(test)]
mod test {
@@ -293,4 +346,28 @@ mod test {
let expected = (4i32, 6f32, 8i32).into_list();
assert!(list.map(Double) == expected);
}
#[test]
fn enumerate_empty() {
assert!(Empty::default().enumerate() == Empty::default());
}
#[test]
fn enumerate_one() {
let list = (2i32,).into_list();
let expected = (Tagged::<P0, _>::new(2i32),).into_list();
assert!(list.enumerate() == expected);
}
#[test]
fn enumerate_multiple() {
use crate::compound::peano::{P1, P2};
let list = (2i32, (), 4f32).into_list();
let expected = (
Tagged::<P0, _>::new(2i32),
Tagged::<P1, _>::new(()),
Tagged::<P2, _>::new(4f32),
).into_list();
assert!(list.enumerate() == expected);
}
}