# Promotion rules - what about when you can't promote?

**URL:** <https://discourse.julialang.org/t/promotion-rules-what-about-when-you-cant-promote/3601>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 8, 2017, 5:48pm UTC](https://discourse.julialang.org/t/promotion-rules-what-about-when-you-cant-promote/3601 "2017-05-08T17:48:02Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ward9250](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ward9250/32/42768_2.png) [@Ward9250](https://discourse.julialang.org/u/Ward9250)\
**Post date:** [May 8, 2017, 5:48pm UTC](https://discourse.julialang.org/t/promotion-rules-what-about-when-you-cant-promote/3601/1 "2017-05-08T17:48:02Z")

</div>

I’m writing some code for the first time dealing with promotion in julia.

Specifically I’m trying to defining some promotion rules for Bio.jl, first a bit of background:

BioJulia defines the following alphabet types:

```julia
"""
Alphabet of biological characters.
"""
abstract Alphabet

"""
DNA nucleotide alphabet.
"""
immutable DNAAlphabet{n} <: Alphabet end

"""
RNA nucleotide alphabet.
"""
immutable RNAAlphabet{n} <: Alphabet end

```

I defined the rules like so:

```julia
for alph in (DNAAlphabet, RNAAlphabet)
    @eval function Base.promote_rule{A<:$alph,B<:$alph}(::Type{A}, ::Type{B})
        return $alph{max(bitsof(A),bitsof(B))}
    end
end

```

So when you have two of the same alphabet (e.g. DNAAlphabet), but with different `n`, then `promote_rule` will return the alphabet with the higher `n` e.g. `promote_rule(DNAAlphabet{4}, DNAAlphabet{2}) == DNAAlphabet{4}`

This is because `DNAAlphabet{4}` is a larger alphabet containing all the elements of the smaller `DNAAlphabet{2}`.

So I then define a promote rule for the sequences that use those alphabets:

```julia
for alph in (DNAAlphabet, RNAAlphabet)
    @eval function Base.promote_rule{A<:$alph,B<:$alph}(::Type{BioSequence{A}}, ::Type{BioSequence{B}})
        return BioSequence{promote_rule(A,B)}
    end
end

a = BioSequence{DNAAlphabet{2}}("aaaaa")
b = BioSequence{DNAAlphabet{4}}("aaaaa")
c = BioSequence{RNAAlphabet{2}}("aaaaa")
d = BioSequence{RNAAlphabet{4}}("aaaaa")

```

Now, using promotion works:

```julia
julia> typeof(promote(a, b))
Tuple{Bio.Seq.BioSequence{Bio.Seq.DNAAlphabet{4}},Bio.Seq.BioSequence{Bio.Seq.DNAAlphabet{4}}}

julia> typeof(promote(c, d))
Tuple{Bio.Seq.BioSequence{Bio.Seq.RNAAlphabet{4}},Bio.Seq.BioSequence{Bio.Seq.RNAAlphabet{4}}}

```

If there isn’t a promote\_rule for the combination of alphabets, promote does no conversion:

```julia
julia> typeof(promote(a, d))
Tuple{Bio.Seq.BioSequence{Bio.Seq.DNAAlphabet{2}},Bio.Seq.BioSequence{Bio.Seq.RNAAlphabet{4}}}

```

Actually in BioJulia you can convert a BioSequence{RNAAlphabet} to a BioSequence{DNAAlphabet}, but it should be a conscious choice and deliberate action to do so, and it should not just be done by a function implicitly through promotion.

So, what is the best thing to do? Does I leave this behaviour as is - where `promote` doesn’t do any conversion in this case?

Or should some rules be added to do some kind of throw ~“Something’s trying to promote a DNA sequence into an RNA one”?

I assume one can make throws happen during `promote` for certain argument types as the docs for promote say:

> Promotion to a common “greater” type is performed in Julia by the promote function, which takes any number of arguments, and returns a tuple of the same number of values, converted to a common type, or _throws an exception if promotion is not possible_.

Thanks,  
Ben.

---

<div class="post-metadata">

**Author:** ![MikeInnes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikeinnes/32/3656_2.png) [@MikeInnes](https://discourse.julialang.org/u/MikeInnes)\
**Post date:** [May 9, 2017, 10:33am UTC](https://discourse.julialang.org/t/promotion-rules-what-about-when-you-cant-promote/3601/2 "2017-05-09T10:33:07Z")

</div>

This seems fine to me. Unlike, say, `convert`, `promote` isn’t meant to be called by users directly, and it doesn’t have a contract that says it must return values of the same type. You can use `promote` to make the Bio.jl interface more convenient but shouldn’t assume it will have any effect.

This also happens with e.g.

```julia
julia> promote(1, :a)
(1, :a)

```

---

<div class="post-metadata">

**Author:** ![Ward9250](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ward9250/32/42768_2.png) [@Ward9250](https://discourse.julialang.org/u/Ward9250)\
**Post date:** [May 9, 2017, 11:21am UTC](https://discourse.julialang.org/t/promotion-rules-what-about-when-you-cant-promote/3601/3 "2017-05-09T11:21:38Z")

</div>

Ok, cool! Thanks Mike!
