Could Julia have implicit type parameters?


#1

I’ve come to realize that (I think) I really want the following to be possible in Julia,

struct Wrapper{T<:SomeAbstractType{S}} <: OtherAbstractType{S}
    t::T
end

This doesn’t work because I have to explicitly declare the S, i.e. Wrapper{S,T<:SomeAbstractType{S}}. The sole reason I don’t want to do this explicitly is because in my actual code which has a few such parameters I’d like to make implicit, things get really really wordy and confusing to read when writing function definitions. If I could define the above, then in theory I would always be able to capture as necessary, as if that S had been explicit, so it seems it could almost just be a cosmetic change:

foo(::Wrapper{<:SomeAbstractType}) = ...
foo(::Wrapper{<:SomeAbstractType{S}}) where {S} = ... # if I need the S

Is there any reason something like this doesn’t exist, or is there any interest for it? I feel like there’s a good chance something like this has been discussed but I couldn’t find anything.


#2

Ahh should have searched a bit more, I see now there’s a pretty recent discussion with links right here Redundant type parameters


#3

this exists on v0.6

Implicit type parameters, e.g. Vector{<:Real} is equivalent to Vector{T} where T<:Real, and similarly for Vector{>:Int} (#20414).

See this:


#4

Both of those function definition exist in 0.6 already in fact, its the struct definition that does not.


#5

I see. Tagged as development.

My hunch is, it’s probably possible to take every type parameter which isn’t specified and place it in there as S <: Any. You’d have to come up with some convention for how the ordering would turn out though. But a good way to see if it would work well would be to try and make it happen with macros.


#6

Yea, I’ve been toying with doing such a workaround by hand, basically

struct Wrapper{T<:SomeAbstractType, S} <: OtherAbstractType{S}
# enforce T <: SomeAbstractType{S} via inner constructor
end

and then (ab)use the fact that Wrapper{T} is an implicit UnionAll over S so you can omit writing the S. It works pretty well, but as mentioned by @jw3126 in the linked post there’s a problem with that Wrapper{T} is not a leaftype, so you can’t write e.g.,

foo(::Type{Wrapper{T}})

you have to either capture S expcitly in these cases, or do,

foo(::Type{<:Wrapper{T}})

which has been seeming to introduce lots of unnecessary ambiguities in my case.