Julia:使用多个参数类型定义promote_规则

Julia:使用多个参数类型定义promote_规则,julia,Julia,假设我想为具有多个参数化类型的类型定义一个promote_rule(),例如,类型MyType: abstract type State end struct Open<:State end struct Closed<:State end struct MyType{T,S<:State} x::T state::S end 根据定义,晋升的结果是一种常见类型。因此,虽然您可以递归地提升Ts,但如果您想保持它们的原样,就必须求助于ss的公共超类型。简单地使

假设我想为具有多个参数化类型的类型定义一个
promote_rule()
,例如,类型
MyType

abstract type State end
struct Open<:State end
struct Closed<:State end

struct MyType{T,S<:State}
    x::T
    state::S
end

根据定义,晋升的结果是一种常见类型。因此,虽然您可以递归地提升
T
s,但如果您想保持它们的原样,就必须求助于
s
s的公共超类型。简单地使用
State
是一个有效的选择,但是
Union
会导致更细粒度的结果:

julia> Base.promote_rule(::Type{MyType{T1, S1}}, ::Type{MyType{T2, S2}}) where {T1, T2, S1, S2} = MyType{promote_type(T1, T2), <:Union{S1, S2}}

julia> promote_type(MyType{Int, Closed}, MyType{Float64, Closed})
MyType{Float64,#s12} where #s12<:Closed

julia> promote_type(MyType{Int, Closed}, MyType{Float64, Open})
MyType{Float64,#s12} where #s12<:Union{Closed, Open}

但一定要测试好各种组合。根据我的经验,第一次晋升和转换确实非常棘手,而且很难做到正确。

谢谢你,这正是我想要的。我有点困惑,为什么我们需要在convert函数中设置子类型
MyType
。在
MyType
的定义中,
S
State
的子类型,
Union{Closed,Open}
也是
State
的子类型,因此
Type{MyType{T}==Type{MyType{T,S
Type
,和其他类型构造函数一样,是。因此,等式,反直觉地说,并不成立。您的参数完全符合逻辑,但这是一个设计选择。
julia> Base.promote_rule(::Type{MyType{T1, S1}}, ::Type{MyType{T2, S2}}) where {T1, T2, S1, S2} = MyType{promote_type(T1, T2), <:Union{S1, S2}}

julia> promote_type(MyType{Int, Closed}, MyType{Float64, Closed})
MyType{Float64,#s12} where #s12<:Closed

julia> promote_type(MyType{Int, Closed}, MyType{Float64, Open})
MyType{Float64,#s12} where #s12<:Union{Closed, Open}
julia> Base.convert(::Type{<:MyType{T}}, m::MyType) where {T} = MyType(convert(T, m.x), m.state)

julia> promote(myFloat, myInt)
(MyType{Float64,Open}(1.0, Open()), MyType{Float64,Closed}(2.0, Closed()))