On Sun, Nov 17, 2013 at 2:08 AM, Niko Matsakis <[email protected]> wrote:

> On Fri, Nov 15, 2013 at 05:05:28PM +0100, Gábor Lehel wrote:
> > I have some ideas about typey things and I'm going to write them down. It
> > will be long.
>
> I haven't read this all yet, I just want to respond to the first few
> paragraphs. :)
>


Thanks!


> > 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.
>
> It's plausible to imagine, though I wouldn't phrase it that "Trait1+Trait2"
> is a trait, but rather a form of generalized object types. Today object
> types have the form `~Trait` and these generalized object types would
> have the form `~(Trait1+...+TraitN)`. Probably their size would be
> N+1 words to account for the extra vtables, which would make it trival
> to support the (natual) subtyping relation of the form
>
>     ~(Trait1+Trait2) <: ~Trait1
>     ~(Trait1+Trait2) <: ~Trait2
>
> You can sort of do something similar today with
>
>     trait Trait3 : Trait1 + Trait 2 { }
>     impl<T:Trait1+Trait2> Trait3 for T { }
>

Interesting. Why would (or should) these two have different
representations? Couldn't we think of `+` as a type constructor, that takes
two traits as arguments and makes a trait?

In the same way that

    type MyThing = (int, f64);

    struct MyThing { a: (int, f64) }

will both have the same representation, couldn't we have `~(Trait1+Trait2)`
be represented just the same as `~Trait3` from the example above, so in a
sense `Trait3` is nothing more than a newtype of `Trait1+Trait2`?

(Couldn't/wouldn't/shouldn't `~Trait3` also be a subtype of `~Trait1` and
`~Trait2`?)

Note that my intuitions here are informed by having done much of the same
things in Haskell with `ConstraintKinds`. For instance, here is Rust's `+`,
but called `:&:`:

http://hackage.haskell.org/package/exists-0.2/docs/Control-Constraint-Combine.html

(And `Exists` in the same package is quite close to Rust's object types.)

But not everything translates directly, because for instance, Haskell
doesn't have subtyping. (Or at least, not in this way -- polymorphic types
with (sub)constraints are in effect a different form of it.)



>
> Note that the current syntax `~Trait:Bounds` is intentionally limited
> in that the traits that can appear in `Bounds` do not offer methods
> but rather give information about the kind of data that the object
> receiver consists of.
>

I know. What I'm trying to explore is whether generalizing the meaning of
`+` might not (alongside being useful generally) remove the need for this
special casing. (My wondering about lifetimes is in a similar vein.)


>
> > 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)`.
>
> I don't think of `'static` as a trait, though it is currently
> implemented that way for historical reasons that will hopefully soon
> be eased. Rather, type parameters can have a *lifetime bound*, which
> indicates the minimum lifetime that they can exist for. `'static` is
> just a special case of this.  This might be (for all intents and
> purposes) what you meant.


Which is a worthwhile question. :-)

I currently have two overlapping interpretations of lifetimes:

 1. The intuitive version, where lifetime parameters on borrowed pointers
and structs have the meaning "this object does not outlive the given
lifetime";

 2. By relating them to the universally quantified type variable of
Haskell's `ST` monad, which seems very close to if not precisely the same
thing: in both cases, objects whose type is tagged with a given
(lifetime/type variable) can't "escape" the given computation.

I can make sense of the "lifetime bounds" on type parameters which you
describe in terms of the first, because it makes sense intuitively, but not
the second. How does a universally quantified type variable end up behaving
in any way, shape, or form like a type class?

In particular, one should be able to do
> `~Trait:'a`, which is interpreted as:
>
>     a pointer to some type T which implements the trait `Trait`
>     and which contains data valid for at least the lifetime 'a
>

Again, in part I'm trying to explore whether the need for this `:` syntax
could be obviated. But for this half of it, in larger part I'm just trying
to understand things.


>
>
> Niko
>



-- 
Your ship was destroyed in a monadic eruption.
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to