The call promote(1:2,[1,2])
throws an error. As far as I understand, this is because on the one hand promote_type(UnitRange{Int64},Array{Int64})
returns AbstractArray{Int64,N} where N
, whereas on the other hand both convert(AbstractArray{Int64},1:2)
and convert(AbstractArray{Int64},[1,2])
will not change their input as they already both belong to AbstractArray{Int64}
.
I understand that there is basically no reason why promote should do anything, as these types of abstract arrays are already compatible in a certain sense, however, the original promote
call then throws an error as the output types are not equal. I wonder a bit why is is.
Lets assume that we declare two (or especially more) structs A
and B
that are involved in a certain type hierarchy (both below the abstract type U
), both of which wrap any kind of abstract array and contain different additional information. Functions on A
and B
may work differently, but mathematically the output is determined only by the contained arrays. Given specific mathematical properties of each the array one captures in A
and B
however, one may do so much faster.
The properties capured by B
are thought to be weaker than A
, such that one might define foo(a::U,b::U) = foo(promote(a,b)...)
where we have some foo(a1::A, a2::A)
.
One could now define promote_rule(::Type{A},::Type{B}) = A
as well as convert(::Type{A}, b::B)
as something that turns b
into the type A
(basically just recalculating the properties captured in A
). However, this is different behavior compared to the AbstractArray behaviour above as we would expect promote_rule(::Type{A},::Type{B}) = U
, and even when one captures the type of the array contained as A{T}
and B{S}
, then promote_rule(::Type{A{T}},::Type{B{S}}) = U{promote_type(T,S)}
will still fail as one runs into the problem explained in the beginning. Is this something promotion should not be used for, and if so, how can one circumvent this problem? After all, there might be many further types thought lower in the hierarchy.
Is it better to manually convert everything into type A
explicitly in the beginning of foo(u1::U,u2::U)
to then call foo(a1::A, a2::A)
and add a function foo(b1::B,b2::B)
? This however feels like imitating promotion in a manual, maybe improper way. It there a kind of “weak” promotion concept that does not enforce equal output types? (thereby however going against the original idea of promotion in the first place)
Or is there a fundamentally different way how one should do these things anyway? The example above might not be the most simple one to choose, but please pardon me some confusion about this on my side despite reading the manual.