Overloading parametric methods - avoiding ambiguity




I have an example over overloading a parametric method that results in an ambiguity error I’d like to avoid.

Say I have the following default method:

abstract Site
immutable NaiveCount

@inline function count_algorithm{T<:Site,A,B}(::Type{T}, ::Type{BioSequence{A}}, ::Type{BioSequence{B}})
    return NaiveCount

So for any two BioSequences the function always returns NaieveCount.

Now say I want to add more specific behaviour for concrete types that <: Site, where if A and B are the same type, then count_algorithm returns something else. I thought this could be achieved by the following:

immutable BitparCount end

immutable Mismatch <: Site end
@inline function count_algorithm{A}(::Type{Mismatch}, ::Type{A}, ::Type{A})
    return BitparCount

However this results in an ambiguity:

julia> # I expect the second method to be the one that applies to this combination of arguments:
julia> count_algorithm(Mismatch, BioSequence{DNAAlphabet{4}}, BioSequence{DNAAlphabet{4}})
ERROR: MethodError: count_algorithm(::Type{Bio.Seq.Mismatch}, ::Type{Bio.Seq.BioSequence{Bio.Seq.DNAAlphabet{4}}}, ::Type{Bio.Seq.BioSequence{Bio.Seq.DNAAlphabet{4}}}) is ambiguous. Candidates:
  count_algorithm{A}(::Type{Bio.Seq.Mismatch}, ::Type{A}, ::Type{A}) at REPL[13]:2
  count_algorithm{T<:Bio.Seq.Site,A,B}(::Type{T}, ::Type{Bio.Seq.BioSequence{A}}, ::Type{Bio.Seq.BioSequence{B}}) at REPL[9]:2

How do I achieve this behaviour whilst avoiding the ambiguity?


Including a constraint for A in the added definition should make this work:

count_algorithm{A<:BioSequence}(::Type{Mismatch}, ::Type{A}, ::Type{A})