Deconstructing UnionAll types

The following naive definition is invalid, but you don’t realize it until you try it:

julia> f(::Type{Set{<:W}} where W) = W
f (generic function with 4 methods)

Here goes…

julia> f(Set{<:Integer})
ERROR: UndefVarError: `W` not defined

I can get the functionality I wanted with a hack:

julia> f_hack(t::Type{Set{<:W}} where W) = t.var.ub
f_hack (generic function with 1 method)

julia> f_hack(Set{<:Integer})
Integer

So how do I do this with public API?

I think you wanted to put the parenthesis before the where, otherwise W is not a parameter of the method, so it can’t be defined in the method body.

Furthermore, the <: doesn’t really make sense there, because it doesn’t allow to unambiguously derive a value for W.

Setting all that aside, it seems that your goal is to find the upper bound for one of the parameters of a UnionAll type? I’m pretty sure that’s not supported, and it also doesn’t seem like something that should be supported. Is there a higher-level problem that lead you to this question?

2 Likes

Thanks @nsako for your reply.

I think you wanted to put the parenthesis before the where , otherwise W is not a parameter of the method, so it can’t be defined in the method body.

Ok, but I still get an error:

julia> f(::Type{Set{<:W}}) where W = W
f (generic function with 1 method)

julia> f(Set{<:Integer})
ERROR: UndefVarError: `W` not defined

Furthermore, the <: doesn’t really make sense there, because it doesn’t allow to unambiguously derive a value for W .

Right, I can see that.

Setting all that aside, it seems that your goal is to find the upper bound for one of the parameters of a UnionAll type?

Yes, that’s what I want.

it also doesn’t seem like something that should be supported.

Why not?

Is there a higher-level problem that lead you to this question?

I’m wanting to do something like this: I have a class of objects, let’s say they are all callable, and a trait input_type(object) with the property that object(x) is defined whenever typeof(x) <: input_type(object). These objects are defined in some third party package and I want to introduce a new trait for these objects output_type(object) which is to have the property typeof(object(x)) <: output_type(object) for all valid x (ones satisfying typeof(x)) <: input_type(object)). I have insight into the package to say things like: if input_type(object) = Set{<:Integer} then an appropriate definition of output_type(object) is Vector{<:Integer}, but don’t know how to articulate this latter insight to write a definition of the derived output_type trait.

1 Like