[rust-dev] Traits proposal

Patrick Walton pwalton at mozilla.com
Fri Jul 6 19:02:30 PDT 2012

On 7/6/12 6:47 PM, Sebastian Sylvan wrote:
> This seems.. quite painful. I would be extremely unlikely to use a
> 'hash' trait in a hash table implementation for this reason. I'd store
> the hash function as a closure in the table itself, and set it up at
> construction (this way you can pass in any hash function provider at
> construction). It almost seems like the guidance for library writers
> would be to avoid traits because they reduce the ability for users to
> compose different behaviors (or at the very least each library would
> provide two versions of everything - one which uses a trait, and one
> which takes the method dictionary at construction time and stores it
> with the data structure).

Yes, it's a drawback. I think Haskell's "sort" and "sortBy" pairs of 
functions are an okay solution (which is basically what you're 
proposing), although not optimal. Most of the time you use the trait 
version of the hash table; in the case in which you need a non-default 
hash function, you use the virtually-dispatched version.

Keep in mind that named impls (as implemented now, and as proposed for 
Haskell) don't really solve the hash table problem, though; if I 
instantiate a hash table and call insert() with the trait instantiated 
for str with FastHash, then I might pass that hash table to someone else 
who calls get() with the trait instantiated for str at QuickHash.

Niko has proposed a general solution, which is basically a refined 
version of the newtype proposal: allow types to be refined with trait 
implementations. So a hash table might have type 
HashMap<str:QuickHash,int>. This is closely related to just wrapping str 
in a newtype, with better ergonomics.

I think the system as proposed could be extended to accommodate this if 
it proves necessary; you would essentially have named implementations 
(or newtypes, if you prefer to look at it that way) that you could wrap 
values in and get out a wrapped version with different trait 
implementations. These wrapped types could be treated as true subtypes, 
so that coercion back and forth is free.

But it seems to me that it's worth trying the proposed system and seeing 
how expressive it turns out to be in practice; we can always layer the 
more sophisticated system on top in the future without breaking 
anything. The ergonomic benefits of not having to import implementations 
in the common case makes coherence worth it, I think.


More information about the Rust-dev mailing list