# Dispatch on precice Union instance in place of subtyping supertype of Union

**URL:** <https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117>\
**Category:** General Usage\
**Tags:** question\
**Created:** [March 28, 2021, 2:48pm UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117 "2021-03-28T14:48:03Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [March 28, 2021, 2:48pm UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117/1 "2021-03-28T14:48:03Z")

</div>

This is a bit tricky I feel, but I didn’t really found out how to separate the two cases.

I have an abstract type `AbstractAgent`. I have a model type which is parameterized on _subtypes_ of my abstract type, see the following MWE:

```julia
abstract type AbstractAgent end

struct ABM{A<:AbstractAgent}
end

struct A <: AbstractAgent
end

model1 = ABM{A}()

struct B <: AbstractAgent
end

struct C <: AbstractAgent
end

model2 = ABM{Union{A, B, C}}()

```

I have a function which I want to make a dispatch on whether the type `A` contained in `ABM` is concrete or a `Union` (I am really targeting unions of concrete types, if that is even possible).

I wrote:

```julia
step!(model::ABM) = println("generic")

step!(model::ABM{A}) where {A<:Union} = println("on union")

step!(model1)
step!(model2)

```

However they both print `generic`, pressumably becase t `A` as well as `Union{A, B, C}` are subtypes of `AbstractAgent`. How can I achieve the dispatch rule I want…?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 28, 2021, 3:13pm UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117/2 "2021-03-28T15:13:33Z")

</div>

Maybe this will avoid dispatch of the Unions as generics?

```julia
step!(model::ABM{T}) where T<: AbstractAgent = println("generic")

```

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [March 28, 2021, 3:23pm UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117/3 "2021-03-28T15:23:20Z")

</div>

Nope, this doesn’t change anything, even if I do not define the method `step!(model::ABM) = println("generic")` at all, and use your suggestion, both calls still yield `generic`.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 28, 2021, 3:34pm UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117/4 "2021-03-28T15:34:19Z")

</div>

> [@Datseris](#):
>
> even if I do not define the method `step!(model::ABM) = println("generic")`

I am not sure if I understand. But it seems that a REPL restart is needed here to remove previous definitions

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [March 28, 2021, 4:04pm UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117/5 "2021-03-28T16:04:02Z")

</div>

I’ve done a REPL restart. Your suggestion does not alter the outcome. This is because `Union{A, B, C} <: AbstractAgent` is true.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 28, 2021, 4:34pm UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117/6 "2021-03-28T16:34:51Z")

</div>

Indeed. Not a solution, but maybe a reflection. Given the similar relationship

```julia
Union{Int32, Int64} <: Integer = true

```

One variable instance can be either one type or the other, so it doesn’t make sense to define a method that is specific for Union types. Except that the variable is a container with more than one value, in which case the dispatch should be on the type of the container.

What you can do is the contrary of being generic:

```julia
julia> not_generic_step!(model) = println("not generic")
not_generic_step! (generic function with 1 method)

julia> step!(model::ABM{A}) = not_generic_step!(model)
step! (generic function with 4 methods)

julia> step!(model::ABM{B}) = not_generic_step!(model)
step! (generic function with 5 methods)

julia> step!(model) = println("generic")
step! (generic function with 3 methods)

julia> step!(model1)
not generic

julia> step!(model2)
generic

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [March 28, 2021, 11:16pm UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117/7 "2021-03-28T23:16:32Z")

</div>

This should work:

```julia
function step!(m::ABM{T}) where T
    if T isa Union
        println("for unions")
    else
        println("generic")
    end
end

```

But I agree with @lmiq that this is an unusual paradigm…

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [March 31, 2021, 10:02am UTC](https://discourse.julialang.org/t/dispatch-on-precice-union-instance-in-place-of-subtyping-supertype-of-union/58117/8 "2021-03-31T10:02:33Z")

</div>

Yeah that works. I was hoping I could avoid `if` statements and only use directly multiple dispatch but I guess it is not possible…
