[rust-dev] paring back the self type to be, well, just a type

Dave Halperin halperin.dr at gmail.com
Thu Apr 12 14:08:11 PDT 2012


Hi,

I've been a lurker on this list for a little while now.  Just thought I'd
point out that the solution to this in Haskell is the 'kind' system, see
http://www.haskell.org/onlinereport/decls.html#sect4.1.1.  The equivalent
of the line 'impl of foo<uint> for uint' would cause an error that foo
requires a type with kind '* -> *'.  Higher kinded types have turned out to
be useful in Haskell.  If you were to try to implement monads in Rust you'd
want to something along the following lines:

iface monad<A> {
    fn bind<B>(fn (A -> self<B>)) -> self<B>;
}

I'm not advocating either way on this in terms of the complexity tradeoff
for adding a kind system, just pointing out that it's what you'd need to
make the current system work and it's not completely crazy to want that
flexibility out of the type system.

Dave

On Thu, Apr 12, 2012 at 12:18 PM, Niko Matsakis <nmatsakis at mozilla.com>wrote:

> I've been reading more closely into the impl/iface code and I think I've
> found another problem. The current `self` type is actually more than a
> type---rather it's a kind of type constructor.  I think we should change it
> to be just a type, because we do not have other type constructors in our
> system and in general things do not hold together.  Let me explain briefly
> what I mean.
>
> Currently, the type `self` refers to "the type implemented the current
> iface".  However, the self type is parameterized just as the containing
> iface.  So, technically, you could have an iface like:
>
>    iface foo<T> {
>        fn bar<S>(x: self<S>);
>    }
>
> Now this would correspond to an impl like:
>
>    impl of foo<T> for [T] {
>        fn bar<S>(x: [S]) { ... }
>    }
>
> Here, the type `self<S>` was transformed to `[S]`.  This is a fairly
> complex transformation, actually, as must "reverse-link" the parameter T
> from its use in `[T]` to the appearance in `foo<T>` and so forth.  In fact,
> this transformation is not especially well-defined: there may be multiple
> types or no types which are equally valid.
>
> To see why there could be multiple types, consider something like `impl<X>
> of foo<T> for either<T,X>`.  What type does `self<S>` have?  It would be
> valid for any `either<S,?>`.
>
> To see why there might be no types, consider something like `impl of
> foo<uint> for uint`.  What type does `self<S>` have?  Or, similarly,
> consider:
>
>    fn some_func<T: foo<uint>>(t: T) {
>        t.bar(...);
>    }
>
> What is the type of the parameter expected by `bar`?
>
> In other languages, there is support for parameterizing a function or type
> by a "type constructor" (which is essentially what `self` is).  I don't
> think we need those capabilities, though of course we could add them later.
>
> I would rather see the `self` type be like any other type parameter:
> non-parameterized.   In that case, the iface shown above would be invalid.
> This does naturally mean that our type system is less expressive.  However,
> its behavior is well-defined in all cases, which seems like a nice property
> to have.
>
>
> Niko
> ______________________________**_________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/**listinfo/rust-dev<https://mail.mozilla.org/listinfo/rust-dev>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20120412/c2ef7de1/attachment.html>


More information about the Rust-dev mailing list