The example in the top comment allows you to implement what it means for a type to "have a `map` function". So it doesn't get rid of the duplicated effort on the "supply side" - we still have to implement the `Mappable` trait for each of `Result` and `Option` individually - but it allows the consumer to not care whether it's got an `Option` or a `Result`, by using only the `Mappable` trait instead. That is newly possible because the GAT feature allows the definition of a `Mappable` trait which contains fresh generics, and `map` is inherently a generic function.
trait X {
type Y<Z>;
}
You couldn't express "a thing that contains another thing" in one of those type expressions before, and also use the contained type. It's needed for Mappable, because it's an abstraction over the concept of modifying a value inside a container.IMO the implementation that they have is a bit obtuse, but I don't know if you can fit something better in this language.
print("Hello")
print("Hello2")
print("Hello3")
print("Hello4")
print("Hello5")
(which I partially copy-pasted above) but I use a for-loop instead.As a library user, you can't copy-paste a line for a type you just created in a library you don't maintain.
Being able to do what you describe lets a maintainer create an interface for all the future types that satisfy given requirements.
Rust is a language with plenty of things to learn, some of which take some time to get used to. And often, having a concrete need for something makes it easier to learn the associated technique.