I don’t think there’s a way to do what you’re asking for. Type aliases with fewer type parameters must make the removed type parameters constant e.g. Vector = Array{T, 1} where T
. In your case, both T
and S
vary, even if S
is intended to entirely depend on T
. There is a good reason for this: S
can’t be specified or proven in the type to entirely depend on T
. For one, the intended dependence is done by a constructor method that is separate from, albeit related to, the type. For another, the dependence requires the constructor method to be pure, which can’t be guaranteed. For example, I could define a widen
method that returns various types depending on a global variable or a random selection, so the same T
could result in different S
across instances. So for guaranteed precision, the type does need both T
and S
as parameters.
Still, you can make assumptions about S
’s dependency on T
to make things easier to read and write. lferrant’s footype(Int)
is the straightforward way to make Foo{Int, widen(Int)}
easier to write (forget the {}
syntax, that’s for writing the precise types). You can overload Base.show
to change how the type is printed. I haven’t actually done this before so I can’t claim this is best practice, but:
# changes how the instance foo32 is printed
function Base.show(io::IO, me::Foo{T,S}) where {T,S}
print(io, "Foo{", T, "~}(", me.data, ", ", me.sum, ")")
end
# changes how the type typeof(foo32) is printed
# I read this is unadvisable but I'm not sure exactly why
# this does prevent printing of S in the precise type
function Base.show(io::IO, me::Type{Foo{T,S}}) where {T,S}
print(io, "Foo{", T, "~}")
end
julia> foo32
Foo{Float32~}(Float32[0.0, 0.0], 0.0)
julia> typeof(foo32)
Foo{Float32~}
julia> Foo{Float32} # this is still abstract, and S is obscured
Foo{Float32~} where S<:Number