On 16/11/13 03:05, Gábor Lehel wrote:
Hello list,

I have some ideas about typey things and I'm going to write them down. It will be long.



No kidding.



It would be nice if `Trait1 + Trait2` were itself a trait, legal in the same positions as any trait. This is already partly true: in trait bounds on type parameters and super-traits of traits. Where it's not true is trait objects, e.g. `~(ToStr + Send)`. Having this could remove the need for the current `~Trait:OtherTraits` special syntax.

I wonder whether lifetimes could also be interpreted as traits, with the meaning: "[object of type implementing lifetime-trait] does not outlive [the given lifetime]". This is an honest wondering: I'm not sure if it makes sense. If it does make sense, it would fit in perfectly with the fact that 'static is already a trait. Together with the above, it might also allow a solution for capturing borrowed data in a trait object: you could write `~(Trait + 'a)`.


How does this interact with vtables?

Note we can already get something similar with

   trait Combine1And2: Trait1 + Trait2 {}
   impl<T: Trait1 + Trait2> Combine1And2 for T {}

   // use ~Combine1And2

which makes it clear how the vtables work, since Combine1And2 has its own vtable explicitly constructed from the two traits. (I guess ~(Trait1 + Trait2) would be most useful if one could cast down to ~Trait1 and ~Trait2.)




The next few are going to be about higher- (or just different-) kinded generics. To avoid confusion, I'm going to use "built-in trait" to mean things like `Freeze` and `Send`, and "kind" to mean what it does everywhere else in the non-Rustic world.

I think the best available syntax for annotating the kinds of types would be to borrow the same or similar syntax as used to declare them, with either `type` or `struct` being the kind of "normal" non-generic types (the only kind of type that current Rust lets you abstract over). [I prefer `type`, because both structs and enums inhabit the same kind.] This is kind of like how C++ does it. For example, the kind of `Result` would be `type<type, type>`. Our `type` corresponds to C++'s `typename` and Haskell's `*`, and `type<type, type>` to C++'s `template<typename, typename> class` and Haskell's `* -> * -> *`. So, for example, you could write the fully kind-annotated signature of an identity function restricted to Result-shaped types (yeah, actually doing this would be pointless!) as:

    fn dumb_id<type<type, type> R, type A, type B>(x: R<A, B>) -> R<A, B>;

To explicitly annotate the kind of the Self-type of a trait, we could borrow the `for` syntax used in `impl`s. Here's the fully kind-annotated version of the `Functor` trait familiar from Haskell:

    trait Functor for type<type> Self {
        fn fmap<type A, type B>(a: &Self<A>, f: |&A| -> B) -> Self<B>;
    }

(Obviously, explicitly annotating every kind would be tiresome, and `Self` is a little redundant when nothing else could go there. I could imagine `trait Functor for type<type>`, `trait Functor for Self`, and/or `trait Functor` all being legal formulations of the above. I'll get back to this later.)



Could this be:

   fn dumb_id<R<type, type>, A, B>(x: R<A, B>) -> R<A, B>;

and

   trait Functor<type> {
       fn fmap<A, B>(a: &Self<A>, f: |&A| -> B) -> Self<B>;
   }

Then something like A<type<type>, type> would correspond to A :: (* -> *) -> * -> *. Speaking of which, could we just use *, `R<*, *>`, `R<*<*>, *>`, `trait Functor<*>`? Although that looks a little cryptic in the nested case.


Huon
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to