Associated types: What are they good for?


#1

I have published the first post on my new GitHub pages blog (basically, a post that got too big for URLO). In this post, I ask an honest question to the reader:

What tangible benefits do associated types really provide over type parameters?

In it, I show how each of the two most obvious reasons for preferring associated types do not actually apply in today’s Rust (or can be achieved through other means), and call out for an example of functionality which could not possibly be implemented without associated types. I hope to be proven wrong!

cc @Centril @lloydmeta as a lot of it relates to frunk (and the “reified indices” feature I’ve been planning)


#2

My understanding is that associated types differ from generic type parameters, first and foremost, in that a specific impl can only implement the said trait once. That’s it. You mention this difference in the blog but sort of appear unsatisifed by it :slight_smile:. I think from purely a design standpoint, that’s all that matters.

It’s indeed unfortunate that associated types don’t influence overlap checking. I also hope that this will be resolved in the future as conceptually it seems completely sound and rational.

Given that associated types are a form of generics, I think the rest comes down to ergonomics. Associated types can be omitted in certain cases, whereas generic type parameters must always be specified. A simple example is:

trait WithAssoc {
     type Assoc: Display;

     fn get(&self) -> &Self::Assoc;
} 

// don’t need to mention Assoc at all
fn foo<W: WithAssoc>(w: W) {
    println!("{}", w.get());
}

Not a big deal at all but an ergonomic improvement. You also mentioned that associated types mimic implied bounds, so you don’t have to repeat things - another ergonomic plus.

I’m also not aware of any significant functionality that can be only implemented with associated types. They’re a form of generics, yet with the restriction of being a single type for a given impl. So given they’re more restrictive, it’s not too surprising that you can’t do more with them. Even if overlap took them into account, you can always solve the overlap with more generic type parameters (again with an ergonomics hit), as you show in the blog.

In the future, generic type constructors will differentiate themselves from generic types. Although I don’t know if that’s still considered associated types or not for the sake of this post.


#3

Ah! Even more tragedy just around the corner!

I had not put two and two together, and still figured that RFC 1672 might allow them to accomplish novel things. :broken_heart: (though I guess it will, in libraries that have not already chosen to go down the rarely-traveled path of “fake associated types” and "yeah, that turbofish needs a _" a la frunk)

Or hmmm… I wonder, maybe there are cases where the number of type parameters needed to accomplish this feat grows exponentially?

Hehe, no question there!

I wouldn’t count them for the sake of this post. They live on a higher plane of existence, and would probably help any other API as equally as they would help reified indices.


#4

Not sure - haven’t thought too hard about it myself :face_with_raised_eyebrow:. At first blush, it would seem you may need more concrete types to “plug the holes”, like the Here and There types in frunk, but I can’t immediately see an exponential element to it. But there may very well be … I think this is the type of weeds only the brave venture off into :slight_smile: