Skip to content

Support map, filter and filter_map with nice ergonomics #91

@stephanemagnenat

Description

@stephanemagnenat

Ferlium now supports reducers (such as fold, count, etc.) with a nice ergonomics: they work both with containers and iterators.

It would be ideal to do the same for mappers (such as map, filter, filter_map, see issues #79 and #78). However, this is more complex, as the return type depends on the input type's structure. One way to deal with that would be to implement generic associated types, somewhat similar to what Rust does.

This would allow to write a Mappable trait:

trait Mappable<Seq, B ↦ Item, MappedSeq<B>> {
    fn map(Seq, (Item) -> B) -> MappedSeq<B>
}

This in turn would allow to implement this trait both on arrays:

impl<A, B> Mappable<Seq = Array<A>, B ↦ Item = A, MappedSeq<B> = Array<B>> {
    fn map(a: Array<A>, f: A -> B) -> Array<B> { ... }
}

and would also work on iterators:

impl<A, B> Mappable<Self = Iterator<A>, B ↦ Item = A, MappedSeq<B> = Iterator<B>> {
    fn map(it: Iterator<A>, f: A -> B) -> Iterator<B> { ... }
}

This approach would work but would require to re-implement Mappable for ever containers, which is acceptable. If we ever have negative impls (and/or specialization), a more generic approach would be possible, to use a blanket implementation for all Seq that are not at the same time Iterator.

In order to implement all functions like map, filter, filter_map, etc. with a single trait, we could define a slightly-more generic trait like this Mappable:

trait Mappable<Seq, B ↦ Item, Iter, MappedSeq<B>>
where
    Iter: Iterator<Item>
{
    fn to_iter(seq: S) -> Iter
    fn from_iter(it: Iter) -> MappedSeq<B>
}

This would be implemented for each container, and blanket-implemented for iterators.

Then a map function could be:

fn map<Seq, B, M: Mappable<Seq, B>>(seq: Seq, f: (M::Item) -> B) -> M::MappedSeq<B> {
    let it = M::to_iter(seq);
    let fm_it = filter_map_iter(it, f);
    M::from_iter(fm_it)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdThe standard librarytypeThe HM(X) type system, excluding the trait part

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions