While working on an exercise on exercism, I found myself struggling with the issue of conversion and promotion.
The exercise called for implementing a user-defined type for complex numbers. Defining the type and the mathematical methods was straightforward, but I when I implemented the conversion and promotion rules, I either had a missing conversion or an ambiguity.
In one of the published solutions, the conversion/promotion is defined as follows:
struct ComplexNumber{T<:Real} <: Number
Re::T
Im::T
end
const jm = ComplexNumber(0, 1)
# a bunch of math operations....
promote_rule(::Type{ComplexNumber{T}}, ::Type{ComplexNumber{S}}) where {T<:Number,S<:Number} = ComplexNumber{promote_type(T,S)}
convert(::Type{ComplexNumber{T}}, x::ComplexNumber{S}) where {T<:Number,S<:Number} = ComplexNumber(convert(T, x.Re), convert(T, x.Im))
ComplexNumber(x::Real, y::Real) = ComplexNumber(promote(x,y)...)
Please explain why this combination of promotion/conversion/construction methods is the (only/recommended?) way
What are the general guidelines when integrating a new type with existing types?