# Correct use of promotion and conversion

**URL:** <https://discourse.julialang.org/t/correct-use-of-promotion-and-conversion/111739>\
**Category:** General Usage\
**Tags:** question\
**Created:** [March 18, 2024, 12:54am UTC](https://discourse.julialang.org/t/correct-use-of-promotion-and-conversion/111739 "2024-03-18T00:54:08Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdsalerno](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdsalerno/32/5539_2.png) [@mdsalerno](https://discourse.julialang.org/u/mdsalerno)\
**Post date:** [March 18, 2024, 12:54am UTC](https://discourse.julialang.org/t/correct-use-of-promotion-and-conversion/111739/1 "2024-03-18T00:54:08Z")

</div>

I defined the following:

```julia
import Base: promote_rule

struct RationalNumber{T<:Integer} <: Real
    num::T
    den::T
end

#RationalNumber{T}(x::S) where {T<:Integer, S<:Integer} = RationalNumber(x, 1) 

RationalNumber(n::T, d::T) where {T<:Integer} = RationalNumber{T}(n,d) 
RationalNumber(n::Integer, d::Integer) = RationalNumber(promote(n,d)...)
RationalNumber(n::Integer) = RationalNumber(n, one(n))
RationalNumber{T}(n::Integer) where {T<:Integer} = convert(T, n) |> RationalNumber

promote_rule(::Type{RationalNumber{T}}, ::Type{S}) where {T,S<:Integer} = RationalNumber{promote_type(T, S)}
promote_rule(::Type{RationalNumber{T}}, ::Type{RationalNumber{S}}) where {T,S<:Integer} = RationalNumber{promote_type(T, S)}

function Base.show(io::IO, r::RationalNumber)
    print(io, "$(r.num)//$(r.den)")
end

```

I am working on getting comparison to behave properly. Currently, it’s fine when I compare a RationalNumber{T} to another with the same T:

```julia
julia> RationalNumber{Int8}(2,3) == RationalNumber{Int8}(2,3)
true

```

But I get an error when comparing a RationalNumber{T} and RationalNumber{U} where T != U:

```julia
julia> RationalNumber(2,3) == RationalNumber{Int8}(2,3)
ERROR: MethodError: no method matching RationalNumber{Int64}(::RationalNumber{Int8})

Closest candidates are:
  (::Type{T})(::T) where T<:Number
   @ Core boot.jl:792
  (::Type{RationalNumber{T}} where T<:Integer)(::Any, ::Any)
   @ Main Untitled-1:848
  (::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number}
   @ Base char.jl:50
  ...

Stacktrace:
 [1] convert(#unused#::Type{RationalNumber{Int64}}, x::RationalNumber{Int8})
   @ Base ./number.jl:7
 [2] _promote
   @ ./promotion.jl:358 [inlined]
 [3] promote
   @ ./promotion.jl:381 [inlined]
 [4] ==(x::RationalNumber{Int64}, y::RationalNumber{Int8})
   @ Base ./promotion.jl:449
 [5] top-level scope
   @ REPL[4]:1

```

I expected my second promote\_rule method to handle this, but I guess I’m misunderstanding something. Can someone help me properly fix this? I’m inclined to write another constructor which handles the MethodError, but I’m not sure if this is the best way to do it.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 18, 2024, 1:07am UTC](https://discourse.julialang.org/t/correct-use-of-promotion-and-conversion/111739/2 "2024-03-18T01:07:36Z")

</div>

> [@mdsalerno](#):
>
> ```julia
> ERROR: MethodError: no method matching RationalNumber{Int64}(::RationalNumber{Int8})
> 
> ```

You’re just missing a constructor that makes a `RationalNumber` from another of a different type:

```julia
RationalNumber{T}(r::RationalNumber) where {T} = RationalNumber{T}(r.num, r.den)

```
