首页 > 解决方案 > Julia:匹配属于联合的任何类型

问题描述

我有一个Union{Type1, Type2, Type3},它匹配所有类型为这些类型之一的值。但是我如何匹配类型本身呢?

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

对于普通类型,这通常是通过 实现Type{MyType}的,其唯一值是MyType。但Type{MyU}仅匹配MyU,而不匹配它包含的类型。我如何匹配这些?

我当然可以只使用DataType,但这有两个问题:

  1. 它匹配任何类型,不仅是我想要的。
  2. 它与 UnionAll 类型不匹配,例如Array.

我目前的解决方法是Union{DataType,UnionAll},但如果我UnionMyU.

我的另一个解决方案是像这样创建第二个并行联合:

MyU = Union{Float64, Int, Array}
MyUT = Union{Type{Float64}, Type{Int}, Type{Array}}

它确实有效并且更严格,但它也很丑陋,并且在手动保持同步时引入了很大的人为错误的可能性。

标签: julia

解决方案


您可以考虑这样的事情来避免宏(这可能很棘手):

gettypes(u::Union) = [u.a; gettypes(u.b)]
gettypes(u) = [u]
typewrap(u) = Union{[Type{v} for v in gettypes(u)]...}

进而:

julia> MyU = Union{Float64, Int, Array}
Union{Float64, Int64, Array}

julia> MyUT = typewrap(MyU)
Union{Type{Array}, Type{Float64}, Type{Int64}}

编辑

作为附加说明,您可以gettypes像这样定义一个班轮:

gettypes(u) = u isa Union ? [u.a; gettypes(u.b)] : [u]

编辑 2

或者更简单,没有中间数组:

typewrap(u) = u isa Union ? Union{Type{u.a}, typewrap(u.b)} : Type{u}

推荐阅读