简体   繁体   中英

Why do I need to define a trait to define an implementation on an external type?

The std::iter library has an AdditiveIter trait which only ever has a single impl :

pub trait AdditiveIterator<A> {
  fn sum(&mut self) -> A;
}

impl<A: Add<A, A> + Zero, T: Iterator<A>> AdditiveIterator<A> for T {
  fn sum(&mut self) -> A {
      let zero: A = Zero::zero();
      self.fold(zero, |s, x| s + x)
  }
}

This trait exists so that we can write foo.iter().sum() . If we were happy with writing sum(foo.iter()) instead, then the above code could be written more simply as:

fn sum<A: Add<A, A> + Zero, T: Iterator<A>>(iter: &mut T) -> A {
    let zero: A = Zero::zero();
    iter.fold(zero, |s, x| s + x)
}

Is there a way to get the best of both? Can I write sum so that:

  • I can use foo.iter().sum() syntax; and

  • I don't have to duplicate the fn sum(&mut self) -> A type signature?

Iterator is not a type, it's actually a trait. If it was a type then this would be possible, something like:

impl<A: Add<A, A> + Zero> Iterator<A> {
  fn sum(&mut self) -> A {
      let zero: A = Zero::zero();
      self.fold(zero, |s, x| s + x)
  }
}

If we could implement methods on a generic type we could do:

impl<A: Add<A, A> + Zero, T: Iterator<A>> T {
  fn sum(&mut self) -> A {
      let zero: A = Zero::zero();
      self.fold(zero, |s, x| s + x)
  }
}

But the compiler doesn't like that, and forces us to define a new trait.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM