Indexed types have their uses but just think about this: for your length-indexed vector example, what if you want to read a file and put its lines into such a vector? Your return type needs the length but it's not known until runtime. Okay you use existential quantification, but you now also need a runtime representation of your types. That's done through singletons. But that destroys Haskell's phase separation and means the inefficient ways you use to prove things and encode naturals now leak to the runtime! Have fun with your unary numbers then.
https://doc.rust-lang.org/nomicon/phantom-data.html
https://doc.rust-lang.org/std/marker/struct.PhantomData.html
So
struct Sender<S> {
/// Actual implementation of network I/O.
inner: SenderImpl;
/// 0-sized field, doesn't exist at runtime.
state: S;
}
I believe could become struct Sender<S> {
/// Actual implementation of network I/O.
inner: SenderImpl;
/// 0-sized field, doesn't exist at runtime.
_marker: PhantomData<S>;
}
I've never used this PhantomData personally, so this might be wrong. Cheers!In Haskell, you can omit these fields entirely, and achieve the same thing just by annotating the function.
For example, in Haskell, we can have
data Const a b = Const a
whereas in Rust, it would be: struct Const<A, B> {
konst: A,
// does not exist at run-time
discard: PhantomData<B>
}Type parameter variance is inferred from usage (e.g. covariant for normal fields, contravariant for function arguments) and without a usage there's no way to infer it.
Nice to see something like this in Rust! One thing that's a bit of a bummer, and I'm sure there are very good reasons for this, is that we HAVE to use every type argument of struct in its definition. If this restriction were to be relaxed, we wouldn't need the "state" field in the struct at all, and we could make the state type variable truly "phantom".
[1] https://www.schoolofhaskell.com/user/konn/prove-your-haskell...
EDIT: Typos.