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.
Ahh should have searched a bit more, I see now there’s a pretty recent discussion with links right here Redundant type parameters
Both of those function definition exist in 0.6 already in fact, its the struct definition that does not.
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.
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.