I don't know why you repeat this incorrect assumption, when I have explained upthread that this is not the case presuming the type system is not allowing subtyping, which means per my example then the type system must enforce immutability when adding an item that has a new data type to the first-class union of the heterogeneous collection. Perhaps you meant in the case that immutability is not enforced by the type system, but as we showed upthread that wouldn't be sound, so I wouldn't create a type system that allows it.
Note even when instead of a first-class union of data types, we employ the conjunction of traits as the ValueType
(which btw is not open to both dimensions of the Expression Problem as we explain upthread) then still can't employ subtyping because Self<T /\ A>
is not a subtype of Self<T>
:
trait Vec<T> {
fn appendItem(&mut self, T) -> Self<T>;
fn appendItem<A>(&self, A) -> Self<T \/ A>;
fn appendItem<A>(&self, A) -> Self<T /\ A>; // Note this can't never be called any way, bcz a conjunction of traits can't be extended bcz we've erased the data types so compiler can't enforce if implementations exist in scope for the added traits
}
So subtyping will never be used in the proposed programming language. Subtyping doesn't exist in Rust now, except for the corner case of lifetimes (which my abstract intuition leads me to believe I will eventually show Rust's lifetimes is an anti-pattern model).
As I showed in my prior example, operations (including appending) which are not adding a new type to the first-class union VaueType
(that is the element type of the heterogeneous collection), will type check with a mutable reference to the collection. And as I also showed in my prior example, operations (including appending) which are adding a new type to the first-class union VaueType
, will not type check with a mutable reference to the collection.
Additionally, when appending an item which adds a new type to the first-class union VaueType
, it is not required to not copy the entire collection in some cases of collection types, e.g. a List
and other types of collections which are inherently encapsulated after append w.r.t. to the ValueType
. It is even possible to make a DiffArray
function like an array for random access, yet make it function like a List
for immutability of ValueType
. I had posted in 2011 a rough conceptual idea which sort of illustrates the conceptual strategies which can be employed to model mutability of arrays in an immutable context. The Clojure collections exhibit other strategies. There does appear to be at least a logarithmic performance penalty for immutability, but again note the distinction here is that I am only proposing to incur that penalty when adding a new data type to the union which is the ValueType
(aka element type) of the collection. So with my proposal we get extension in both directions (dimensions) of the Expression Problem, yet we don't prematurely erase the union of data types and pay no penalty for not erasing them, until if ever we need to do dependency injection extension along the data type direction of the Expression Problem by actually adding a new data type to preexisting element type of a preexisting collection which we couldn't otherwise do (this dependency injection) in the current way Rust, Haskell, and PureScript (typeclass languages) are. Of course subtyping+subclassing languages such as C++, C#, Scala, OCaml, etc.. are hopeless anti-patterns.