3 ms·
The litmus test for “typeness” is to ask whether it makes sense to ask whether a term has the type in question. For example, it makes sense to ask whether 2 has
by catnaroek 10y ago
The litmus test for “typeness” is to ask whether it makes sense to ask whether a term has the type in question. For example, it makes sense to ask whether 2 has type string, and the answer is “no”. But it doesn't make sense to ask whether 2 has type 3 - the closest thing to an answer is “what the hell I don't even?” Then:
(0) Structs and interfaces are unarguably types.
(1) If a struct S has all the methods required by an interface I, then every term of type S also has type I.
As for coercions, they are one possible implementation of subtyping. Another possible implementation is guaranteeing that, whenever “Foo <: Bar”, then “Foo” and “Bar” have a common in-memory representation.
But languages shall never be conflated with their implementation details!
- burntsushi 10y agoYes, I think pcwalton saying that Go doesn't have subtyping is very confusing. What I think he was trying to say was that Go's subtyping is strange because everything is invariant, and that the use of coercions makes the questions you initially raised perhaps not so interesting. For example, if you start with some base assumptions about which type constructors in Go are invariant, e.g., pointers, slices, arrays, etc., then you could feasibly come up with a rule like this: If T <: U, then Foo<T> <: Foo<U> if Foo's type parameter doesn't appear within an invariant type constructor in the definition of Foo. If a rule like that is all you need (and those types of rules have precedence in Go, like whether a type permits equality comparisons or not), then I think that more or less backs up pcwalton's point that subtyping isn't necessarily the thing you have to worry about when adding parametric polymorphism to Go. It's the other stuff, like the mentioned zero values and presence of `nil`.
- catnaroek 10y agoThe concern I initially raised is just that retrofitting parametric polymorphism into a statically typed language with subtype polymorphism and a sizeable codebase worth not breaking... has a history of not going so well. Although zero values are inelegant, I don't see why they would interact so badly with parametric polymorphism. In Rust terms, it's as if every type implicitly implemented the Default trait. (EDIT: You're right, steveklabnik. It's closer to Default than to Zero. Thanks!) As for nil, I'd rather not comment, since I'm not familiar with the specifics of how it works in Go. (But a previous conversation with pcwalton made it perfectly clear that it doesn't work the same as in Java or .NET.)
- steveklabnik 10y ago(I think it's closer to Default than Zero, personally.)