首页 > 解决方案 > Julia:使用多种参数类型定义promote_rule

问题描述

假设我想为promote_rule()具有多种参数类型的类型定义 a ,例如 type MyType

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

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

有没有办法定义一个promote_rule()只促进第一种而不是第二种的方法,例如:

myFloat = MyType(1.0, Open()) # MyType{Float64, Open}
myInt = MyType(2, Closed()) # MyType{Int64, Closed}
promote(myFloat, myInt)
# (MyType{Float64, Open}, MyType{Float64, Closed})

标签: julia

解决方案


根据定义,提升的结果是一种常见的类型。因此,虽然您可以递归地提升s,但如果您想保持原样,则必须使用 sT的通用超类型。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的工作方法promote;具体来说,忽略状态类型:

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()))

但一定要很好地测试各种组合。以我的经验,促销和转换真的很繁琐,而且很难在第一次就做好。


推荐阅读