Reputation: 239
I have a Union{Type1, Type2, Type3}
, which matches all values whose type is one of those types. But how do I match the types themselves?
MyU = Union{Float64, Int, Array}
a::MyU = 3.5 # works
a = 5 # works
a = [1, 2, 3] # works
# but of course
a = Float64 # nope
a = Int # nope
a = Array # nope
With normal types this is usually achieved via Type{MyType}
, whose only value is MyType
. But Type{MyU}
matches only MyU
, and not the types it contains. How do I match those?
I can of course just use DataType
, but this has two issues:
Array
.My current workaround is Union{DataType,UnionAll}
, but it's an ugly hack that is additionally bound to crash and burn if I include another Union
or some other non-concrete type into MyU
.
My other solution is to make a second, parallel Union like so:
MyU = Union{Float64, Int, Array}
MyUT = Union{Type{Float64}, Type{Int}, Type{Array}}
It does work and is more strict, but it's also ugly and introduces large possibility of human error with manually keeping those in sync.
Upvotes: 4
Views: 686
Reputation: 69939
You could consider something like this to avoid macros (which can be tricky):
gettypes(u::Union) = [u.a; gettypes(u.b)]
gettypes(u) = [u]
typewrap(u) = Union{[Type{v} for v in gettypes(u)]...}
and then:
julia> MyU = Union{Float64, Int, Array}
Union{Float64, Int64, Array}
julia> MyUT = typewrap(MyU)
Union{Type{Array}, Type{Float64}, Type{Int64}}
EDIT
As an additional note, you can define gettypes
as one liner like this:
gettypes(u) = u isa Union ? [u.a; gettypes(u.b)] : [u]
EDIT 2
Or yet simpler without an intermediate array:
typewrap(u) = u isa Union ? Union{Type{u.a}, typewrap(u.b)} : Type{u}
Upvotes: 4