Using eg the solution you did above. AFAIK you cannot parametrize type names, only type parameters, which makes sense if you think about it.
If you definitely want to enforce that eg both mat and vec are Array, use an inner constructor. But IMO it should not be necessary in most cases I can think of, there is no reason not to keep your code fully generic. Recently I got into the habit of even leaving out the supertypes, and just relying on duck typing (“if it breaks, you will know”).
IMO the protection from overspecifying types is partly an illusion (even though I also use it). It just makes your code somewhat brittle, as subtyping does not allow something to conform to two disjoint interfaces — eg something can be an <: AbstractArrayand something else at the same time.
Also, duck typing (allowing things to fail because methods are undefined) will lead to an error anyway.
Just to make this a bit more concrete — you can’t do this because type parameters don’t have a generic meaning. The first type parameter is not always the element type. The second type parameter is not always the dimensionality. A great example is BitArray: it only has one parameter and thus could not be meaningfully substituted in for R in your example. Conversely matrices like SparseMatrixCSC and Diagonal don’t have a dimensionality parameter since they are by definition 2-dimensional.
The way to enforce a constraint like this is just through the constructor.
Yes I agree about the “illusion ” part. Nonetheless I sometimes still want to have something like “enforcement of encapsulation” or “gerrenteed correctness/throw ”. The Julia language itself enforced so little that I often feel a lack of discipline. I am looking in established projects for ideas but has yet to distill enough essences to form some doctrines like one would find in any book about c++ design patterns.