cross: list: implement a Map operation
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user