Map passed in iterator from T -> T2 and pass resulting iterator to another

Given this trait

trait Trait1<I> {
    fn foo(&self, _: I);
}

and this struct

struct Map1<T, T2, I, I2, Tr: Trait<I2>>(Box<dyn Fn(T) -> T2>, T2) // I know phantomdata is needed for I and I2
    where
        I: Iterator<Item = T>,
        I2: Iterator<Item = T2>;

how can I impl Trait1 for Map1 such that

impl<T, T2, I, I2, Tr: Trait<I2>> Trait1<I> for Map1<T, T2, I, I2, Tr: Trait<I2>>
    where
        I: Iterator<Item = T>,
        I2: Iterator<Item = T2>
{
     fn foo(&self, i: I) {
          let i2: I2 = i.map(&self.0); // error expected I2 found Map
          self.1.foo(i2);
     }
}

I'm trying to allow the impl of Map1 to hold an Trait1 object that expects something of type I2. I want the impl of Map1 to 'wrap' an incoming iterator I, with a map like iterator to transform types T to T2 and pass the resulting iterator to self.1.
self.1 should not know it is receiving a Map, just that it's receiving an iterator.

I'm not trying to re-invent map or anything. This is just a simplified, contrived example.

<T as Iterator>::map() returns Map<T, F>. It's not an arbitrary iterator; it's exactly the Map<…> type. But a generic type parameter on a function means that the caller can choose what type it will stand in for. But that's obviously wrong: if I call the function in a way that I2 = String or I2 = u32, for example, then that's of course not Map.

You probably want to get rid of the I2 type parameter as well as the explicit type annotation in the implementation altogether. The mapped iterator type is not something that the caller can determine, it's always Map<>, furthermore it's an implementation detail, so it doesn't need to, and shouldn't, be in the declaration.

I'm not sure what you are trying to do with the Tr type parameter, since it's never used in the code, but after removing it, the following compiles:

struct Map1<T, T2, I, I2>(Box<dyn Fn(T) -> T2>, T2, PD<I>, PD<I2>);

impl<'a, T, T2, I> Trait1<I> for Map1<T, T2, I, Map<I, &'a dyn Fn(T) -> T2>>
    where
        I: Iterator<Item = T>,
        for<'b> T2: Trait1<Map<I, &'b dyn Fn(T) -> T2>>
{
     fn foo(&self, i: I) {
          let i2 = i.map(&*self.0);
          self.1.foo(i2);
     }
}
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.