# Understanding promotion

**URL:** <https://discourse.julialang.org/t/understanding-promotion/6218>\
**Category:** New to Julia\
**Created:** [October 3, 2017, 1:23pm UTC](https://discourse.julialang.org/t/understanding-promotion/6218 "2017-10-03T13:23:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Philippe\_Maincon](https://avatars.discourse-cdn.com/v4/letter/p/a4c791/32.png) [@Philippe\_Maincon](https://discourse.julialang.org/u/Philippe_Maincon)\
**Post date:** [October 3, 2017, 1:23pm UTC](https://discourse.julialang.org/t/understanding-promotion/6218/1 "2017-10-03T13:23:50Z")

</div>

I am exploring whether I can get some oo behaviour (data inheritance) in Julia, but that is not my question today. In that exploration I have this code that, to my surprise, fails:

```julia
abstract type Family end
type Parent <: Family
    a::Float64
end
type Child <: Family
    a::Float64
    parent::Parent
end
convert(::Type{Parent},x::Child) = x.parent
promote_rule(::Type{Child},::Type{Parent}) = Parent
combine(x::Parent,y::Parent) = print("Two Parents\n")
combine(x::T,y::T) where {T<:Family} = combine(x.parent,y.parent)

p = Parent(1.)
c = Child(3.,p)
combine(c,p)

```

The above fails. I expect Julia to use my promotion rule, convert Child to Parent, and thus call my second “combine” method (which then calls the first “combine” method.

No joy. Julia points out that there is no combine(::Child,::Parent) method. Where did I go wrong?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 3, 2017, 1:38pm UTC](https://discourse.julialang.org/t/understanding-promotion/6218/2 "2017-10-03T13:38:41Z")

</div>

1. You need to either import `convert` and `promote_rule` or prefix with `Base`:

```julia
Base.convert(::Type{Parent},x::Child) = x.parent
Base.promote_rule(::Type{Child},::Type{Parent}) = Parent

```

1. Julia doesn’t do implicit promotions, hence:

```julia
combine(x::Family, y::Family) = combine(promote(x, y)...)

```

1. 

```julia
julia> combine(c,p)
Two Parents

```

---

<div class="post-metadata">

**Author:** ![Philippe\_Maincon](https://avatars.discourse-cdn.com/v4/letter/p/a4c791/32.png) [@Philippe\_Maincon](https://discourse.julialang.org/u/Philippe_Maincon)\
**Post date:** [October 3, 2017, 2:03pm UTC](https://discourse.julialang.org/t/understanding-promotion/6218/3 "2017-10-03T14:03:25Z")

</div>

Thanks. I keep forgetting to import!!! I’ll use the module.Function syntax in the future, as you suggest.

No implicit promotion, that’s very important. But I made that mistake for a reason: still playing around, I programmed “dual numbers” (automatic differentiation). There I have

```julia
convert(::Type{Dual} ,x::Float64) = Dual(x,0.)
promote_rule(::Type{Dual} ,::Type{Float64) = Dual
+(a::Dual,b::Dual) = Dual(a.x+b.x, a.dx.+b.dx)
*(a::Dual,b::Dual) = Dual(a.x*b.x, a.dx.*b.x.+b.dx.*a.x)

```

(no explicit call to “promote”) and I can combine Float64 and Dual…

It’s not the first time I get great help from you 😀

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 3, 2017, 2:34pm UTC](https://discourse.julialang.org/t/understanding-promotion/6218/4 "2017-10-03T14:34:41Z")

</div>

That is because of: [https://github.com/JuliaLang/julia/blob/b3241d7845f136d1f400f7283ae37128250d2883/base/promotion.jl#L276](https://github.com/JuliaLang/julia/blob/b3241d7845f136d1f400f7283ae37128250d2883/base/promotion.jl#L276)

```julia
+(x::Number, y::Number) = +(promote(x,y)...)
*(x::Number, y::Number) = *(promote(x,y)...)
-(x::Number, y::Number) = -(promote(x,y)...)
/(x::Number, y::Number) = /(promote(x,y)...)

```

i.e. all numbers promote with `+`, `*`, `-`, `/`.

---

<div class="post-metadata">

**Author:** ![Philippe\_Maincon](https://avatars.discourse-cdn.com/v4/letter/p/a4c791/32.png) [@Philippe\_Maincon](https://discourse.julialang.org/u/Philippe_Maincon)\
**Post date:** [October 5, 2017, 6:36am UTC](https://discourse.julialang.org/t/understanding-promotion/6218/5 "2017-10-05T06:36:31Z")

</div>

Thanks! I had writen an answer before you last post, but apparently did no “press return”:

* * *

Gosh am I slow!

Of course, somewhere in Julia there is something like

```julia
+(x,y) = +(promote(x,y)...)

```

which is why my “dual” code works while I need to promote in my “Family” code.

: )
