cross: list: implement a Map operation

This commit is contained in:
2022-08-15 20:59:51 -07:00
parent 96c690990f
commit 1cff95877e

View File

@@ -94,7 +94,7 @@ where
// - [ ] as_ref (maps every element E to &E)
// - [ ] as_mut (maps every element E to &mut E)
// from this we can construct:
// - [ ] map (calls into fold, with the accumulator being Appendable::append)
// - [x] map (calls into fold, with the accumulator being Appendable::append)
// - [ ] visit (calls into fold, with a no-op accumulator)
// - [ ] visit_ref, visit_mut (calls as_ref/as_mut, then visit)
// - [ ] enumerate (calls fold, with the accumulator being a Peano counter + value copy)
@@ -173,6 +173,38 @@ where
}
}
pub trait MapVisitor<V> {
type Output;
fn map(&self, elem: V) -> Self::Output;
}
pub struct MapOp<F>(F);
impl<Prev, Next, F> FoldOp<Prev, Next> for MapOp<F>
where
F: MapVisitor<Next>,
Prev: Appendable<F::Output>,
{
type Output = Appended<Prev, F::Output>;
fn feed(&self, prev: Prev, next: Next) -> Self::Output {
prev.append(self.0.map(next))
}
}
pub trait Map<Visitor> {
type Output;
fn map(self, op: Visitor) -> Self::Output;
}
impl<L, Visitor> Map<Visitor> for L
where
L: Fold<MapOp<Visitor>, Empty>
{
type Output = L::Output;
fn map(self, visitor: Visitor) -> Self::Output {
self.fold(MapOp(visitor), Empty::default())
}
}
#[cfg(test)]
mod test {
@@ -226,7 +258,7 @@ mod test {
#[test]
fn reverse_empty() {
Empty::default().reverse();
assert!(Empty::default().reverse() == Empty::default());
}
#[test]
@@ -235,4 +267,30 @@ mod test {
let expected = (5u32, 4f32, 3i32).into_list();
assert!(list.reverse() == expected);
}
struct Double;
impl MapVisitor<i32> for Double {
type Output = i32;
fn map(&self, v: i32) -> Self::Output {
v + v
}
}
impl MapVisitor<f32> for Double {
type Output = f32;
fn map(&self, v: f32) -> Self::Output {
v + v
}
}
#[test]
fn map_empty() {
assert!(Empty::default().map(Double) == Empty::default());
}
#[test]
fn map_mixed() {
let list = (2i32, 3f32, 4i32).into_list();
let expected = (4i32, 6f32, 8i32).into_list();
assert!(list.map(Double) == expected);
}
}