Hacker News new | ask | show | jobs
by armchairhacker 688 days ago
> IF a function expects a value with a linear type, can you pass an a value with an exponential type to it? The answer is that you can. Try this in linear haskell if you don't believe me.

> Those familiar with rust will notice that this is not how rust works. If a function takes T, and you have &T, you just cannot call that function. (Ignore Clone for now.)

I think this is wrong. An exponential type in Rust is a type that implements `Copy`. The analogy in Rust is:

    fn linear_fun<T>(x: T) {
        // ...
    }

    fn main() {
        let foo = 5;
        linear_fun(foo);
        println!(foo);
    }
And that compiles fine: `foo` is implicitly copied to maintain that `linear_fun` owns its parameter.

You can ignore `Clone`, but ignoring `Copy` destroys the premise, because without it Rust has no exponential types at all.

EDIT: I agree Rust solves the issue of mutability fairly well. Furthermore, I think practical linear types can be added to a Rust-like type system with Vale's (https://vale.dev/) Higher RAII, where a "linear type" is an affine type that can't be implicitly dropped outside of its declaring module.

I don't know if this is what Vale does, but to enforce "can't be implicitly dropped outside of its declaring module" in Rust I would add two changes:

- Whenever the compiler tries to insert implicit drop code for a linear type outside of its declaring module, it instead raises an error.

- Type parameters get an implicit `Affine` auto-trait, like `Sized`. If a type parameter is `?Affine`, the compiler will refuse to insert implicit drop code. Standard library generic parameters will be `?Affine` wherever possible, e.g. containers like `Vec` and `HashSet` will have `T: ?Affine`, but the methods that could implicitly destroy an element like `HashSet::insert` will have plain `T`.

1 comments

> You can ignore `Clone`, but ignoring `Copy` destroys the premise, because without it Rust has no exponential types at all.

it somewhat strains the analogy because rust is implemented in a very elegant way (where references can be used multiple times because they implement Copy), but the analogy to exponentials in rust would be references. Just imagine clone and copy aren’t a thing, and that references have a special case that allow them to be used multiple times while owned values can be used at most once. The thing to note is that if you have an owned value, you can pass a reference to it to as many functions as you want (so long as those functions expect references). But if you have a reference, you can’t pass it to a function that expects an owned value unless the type provides you a way to make a copy.

You can imagine starting with this and then building up to rust in a nice way. You first implement passing an owned value as a move. Then first add types that can be used multiple times because they are still valid after a move. (the Copy trait.) And then you make references Copy since they meet that criteria.