# How to dispatch on a type alias?

**URL:** https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476
**Category:** New to Julia
**Created:** [November 20, 2023, 5:27pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476 "2023-11-20T17:27:46Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 5:27pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/1 "2023-11-20T17:27:46Z")

</div>

I have trouble implementing the dispatch I want using type aliases. I want to dispatch on `Type{A{T1,B{T3}}} where {T1,T3}`, but i do not find the right syntax. I currently have something that looks like :

```julia
struct A{T1,T2}
    x::T1
    y::T2
end

struct B{T3}
    z::T3
end
# an alias : 
const C{T1,T3} = A{T1,B{T3}}
# and a constructor : 
C(x,z) = A(x,B(z))

c = C(1,2.)
typeof(c) # returns C{Int64, Float64} (alias for A{Int64, B{Float64}})

function myfunction(::Type{A{T1,B{T3}}}) where {T1,T3}
    return 1
end

myfunction(C) # Errors....

```

The function already dispatches on e.g. `typeof(c)`, but not on `C` itself.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [November 20, 2023, 5:46pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/2 "2023-11-20T17:46:24Z")

</div>

The `Type{...}` type is itself invariant. So you want:

```julia
function myfunction(::Type{T}) where {T<:A{T1,B{T3}} where {T1, T3}}
    return 1
end

```

or even just

```julia
myfunction(::Type{C}) = 1

```

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 6:01pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/3 "2023-11-20T18:01:55Z")

</div>

Thanks @mbauman this is working correctly indeed… but it is not what I needed… By my fault, not yours.

With a closer look, the problem is in fact the following:

```julia
function second_function(::Type{T}) where {T<:A{T1,G} where {T1, G}}
    # I need to know which type is G :
    return G 
end

```

The issue is that I need to access the fact that the inner type is “B” from inside the function… and it tells me that

```julia
julia> second_function(C)
ERROR: UndefVarError: `G` not defined
Stacktrace:
 [1] second_function(#unused#::Type{C})        
   @ Main .\Untitled-1:20
 [2] top-level scope
   @ Untitled-1:25 

```

The thing is that I want to dispatch on G inside the function.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [November 20, 2023, 6:05pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/4 "2023-11-20T18:05:19Z")

</div>

Then you “raise” the `G` type parameter up to the function level (instead of being buried in `T`):

```julia-repl
julia> function second_function(::Type{T}) where {G, T<:A{T1,G} where T1}
           return G
       end
second_function (generic function with 1 method)

julia> second_function(C{1,2})
B{2}

```

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 6:08pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/5 "2023-11-20T18:08:35Z")

</div>

This is it. But now why is’nt `second_function(C)` working ? I understand that `C` is not a type but a group of types… But I really only want `B` and not `B{T3}` to be returned. Afterall,

```julia
julia> C
C (alias for A{T1, B{T3}} where {T1, T3})      

julia> 

```

So the information that the second slot of `C` is `B{T3} where T3` is there in the object.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [November 20, 2023, 6:19pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/6 "2023-11-20T18:19:28Z")

</div>

I think that’s just a rule of how dispatch with type parameters works — it requires matching against a fully-resolved type. So I don’t think you’ll ever get a type parameter with a `where` clause inside a function.

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 6:20pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/7 "2023-11-20T18:20:36Z")

</div>

So I cannot dispatch on `C` at all without specifying more (like `C{1,2.}`) you used ?

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [November 20, 2023, 6:21pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/8 "2023-11-20T18:21:21Z")

</div>

Sure you can — it’s just a different method: `second_function(::Type{C}) = B{T3} where T3`.

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 6:25pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/9 "2023-11-20T18:25:32Z")

</div>

> [@mbauman](#):
>
> second\_function(::Type{C}) = B{T3} where T3

Yes this is the behavior I want. But I want is for several types at once :

```julia
struct B1{T3} 
    y::T3
end
const C1{T1,T3} = A{T1,B1{T3}}

struct B2{T3} 
    y::T3
end
const C2{T1,T3} = A{T1,B2{T3}}

struct B3{T3} 
    y::T3
end
const C3{T1,T3} = A{T1,B3{T3}}

struct B4{T3} 
    y::T3
end
const C4{T1,T3} = A{T1,B4{T3}}

# I have like 12 of them

```

So IIUC I have to define all the methods:

```julia
second_function(::Type{Ci}) = inner_method(Bi)

```

to be able to simply dispatch on this ?

If yes then this is not a huge problem I can copy/paste

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [November 20, 2023, 7:30pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/10 "2023-11-20T19:30:24Z")

</div>

That sure looks like you’re wading into some pretty dark and scary woods… there will surely be more dragons lurking about. I’m afraid I don’t have more concrete suggestions given the sketchy nature here, but it looks fraught to me.

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 7:36pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/11 "2023-11-20T19:36:39Z")

</div>

I Will try to setup a more detailed example so that we can start talking reasons for doing that and options to get out of those woods then I think.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 20, 2023, 7:57pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/12 "2023-11-20T19:57:31Z")

</div>

> [@mbauman](#):
>
> I think that’s just a rule of how dispatch with type parameters works — it requires matching against a fully-resolved type.

I’ve been thinking of it in my head as method `where` clauses requiring the parameters be specified because they may be matched across multiple arguments or be accessible values in the method body. Reminds me of this past thread, I’ll just share the last small example sans the thread’s context:

> [@Question on manual subsection: Extracting the type parameter from a super-type](https://discourse.julialang.org/t/question-on-manual-subsection-extracting-the-type-parameter-from-a-super-type/97137/4):
>
> Incidentally, this is where it is important to specify parameters belonging to the argument versus the method. A version of the correct code for the number of dimensions would look like
> 
> ```julia
> my_ndims(::Type{<:AbstractArray{T,N} where T}) where {N} = N
> 
> my_ndims(Union{Array{Int,1}, Array{Bool,1}}) # 1
> 
> ```
> 
> `Base.ndims` now behaves like this, but it used to error on unspecific `T` like this `Union` or `Array{T,1} where T` because its method had both parameters `{T,N}` (issue [#40682](https://github.com/JuliaLang/julia/pull/40682)).

As for this particular case:

```julia
# works for _(C), fails for _(C{Int, Float64})
function myfunction(::Type{ A{T1,B{T3}} where {T1,T3} })
  return 1
end

# names disambiguated to avoid multimethods
# works for _(C{Int, Float64}), fails for _(C)
function myfunction1(::Type{ A{T1,B{T3}} }) where {T1,T3}
  return 1
end

function myfunction2(::Type{ A{T1,B{T3}} } where {T1, T3})
  return 1
end

```

As said before, method parameters must be specified, so `myfunction1` failing makes sense. `myfunction2` fails because the parametric `Type` requires that the `T1` and `T3` be specified, in the same way that `D = Vector{Ref{T}} where T` only includes `Vector{Ref{Int}}` or `Vector{Ref{Float64}}`, but not `Vector{Ref}`.

In fact `myfunction1` and `myfunction2` would override each other with the same function name because the argument requires specified `T1` and `T3`, despite not being equivalent (`T1` and `T3` are not available in the method body nor can they matched across arguments).

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 8:14pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/13 "2023-11-20T20:14:05Z")

</div>

Well, it does not look like your version solves my problem : I need to avoid rewriting it for B1,B2,B3…

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [November 20, 2023, 8:28pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/14 "2023-11-20T20:28:50Z")

</div>

My hunch is that all these types should just be one type, potentially parameterized, but mostly storing the distinctions between them as _data_ in the fields. It’s likely going to be hard to preserve type stability — especially if you _want_ to have functions returning `UnionAll`s, for example — and then you might as well just use `if`s instead of dispatch in any case.

But again, hard to say.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 20, 2023, 8:34pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/15 "2023-11-20T20:34:06Z")

</div>

Right, I wasn’t addressing that, just how type parameters work. You could avoid _manual_ copies and rewrites with metaprogramming, something like:

```julia
for i in 1:4
    # make Symbols representing the variables
    Bi = Symbol('B'*string(i))
    Ci = Symbol('C'*string(i))
    # @eval this block in the global scope
    # @eval allows interpolation of Symbols into the expression
    @eval begin
         struct $(Bi){T3} 
             y::T3
         end
         const $(Ci){T1,T3} = A{T1,$(Bi){T3}}
    end
end

```

But this is assuming that you are making a MWE that doesn’t show the utility, otherwise I would caution you against making so many types with the same structure _and_ methods, that could just be 1 type.

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 9:04pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/16 "2023-11-20T21:04:52Z")

</div>

Thanks for the metaprogramming, this is the right solution to meet my criterias indeed. However:

> [@mbauman](#):
>
> My hunch is that all these types should just be one type, potentially parameterized, but mostly storing the distinctions between them as _data_ in the fields. It’s likely going to be hard to preserve type stability — especially if you _want_ to have functions returning `UnionAll`s, for example — and then you might as well just use `if`s instead of dispatch in any case.

> [@Benny](#):
>
> otherwise I would caution you against making so many types with the same structure _and_ methods, that could just be 1 type.

I agree completely with these statements, and therefore if you want to read the following I’ll describe a bit more the issue I am having so that we may or may not conclude on a different API.

I have an abstract `Generator` type with approx 12 generators implemented (but more expected in the future), with “known” names:

```julia
abstract type Generator end
(G::Generator)(x) = # this method should be implemented for all generator. 
# then I have several generator: 
struct ClaytonGenerator <: Generator end
struct GumbelGenerator <: Generator end 
# and all implement the same functor method. 

```

For simplicity i give them no parameters at all but all have fields in them and are fundamentally different from each other.

Then I have the main type of the problem, that implements something on top of a generator:

```julia
struct Archimedean{d, TG}
    G::TG
    function Archimedean(d,G)
        new{d,typeof(G)}(G)
    end
end

```

This interface is _hidden_ from the user through a set of aliases:

```julia
const Clayton{d} = Archimedean{d, ClaytonGenerator}
Clayton(d,...) = Archimedean(d,ClaytonGenerator(...)) # again, there are parameters in the true model

const Gumbel{d} = Archimedean{d, GumbelGenerator}
Gumbel(d,...) = Archimedean(d,GumbelGenerator(...)) # again, there are parameters in the true model

```

In fact, the users might not even know that the generators exists (but if they do, they are also exposed), and these names are “known” from the litterature.

All those objects are _models_, that you can fit to a dataset via :

```julia
fit(Clayton,data)
fit(Gumbel,data)

```

At least, that was the interface I had before, when `Clayton, Gumbel, ...` where their own types `<:Archimedean` and the Generators were just methods from these types. But now I have another kind of model, that is supposed to take the same place in the structure as the Archimedean type, and leverage the implementation of the generators.

Since the Generator is in facrt the stuff that needs to be fitted, I wanted to devise, from only the `Clayton` object, that the right generator to use is the `ClaytonGenerator`.

So there are two goals :

1. Keep the outside fitting interface that is already there
2. Move generators out of the `Clayton` and `Gumbel` structs to be able to leverage them at other places of the code.

Thaughts ?

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 20, 2023, 9:22pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/17 "2023-11-20T21:22:34Z")

</div>

> [@lrnv](#):
>
> I wanted to devise, from only the `Clayton` object, that the right generator to use is the `ClaytonGenerator`

Can’t say for sure since I don’t understand the full API, but this sounds similar to a Holy trait.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [November 20, 2023, 9:31pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/18 "2023-11-20T21:31:28Z")

</div>

Ah, then types indeed might be the answer! But in many cases, I’ve found it easier to dispatch on _values_ rather than types, even if those values are just singletons that flag which generator to use.

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [November 20, 2023, 10:12pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/19 "2023-11-20T22:12:22Z")

</div>

> [@Benny](#):
>
> Can’t say for sure since I don’t understand the full API, but this sounds similar to a Holy trait.

Hum… Not sure about how it would solve my issue of not being able to find the generator from the alias, since I cannot dispatch on the alias…

> [@mbauman](#):
>
> Ah, then types indeed might be the answer! But in many cases, I’ve found it easier to dispatch on _values_ rather than types, even if those values are just singletons that flag which generator to use.

I agree. But the `fit` API is not mine and comes from [Distribution Fitting · Distributions.jl](https://juliastats.org/Distributions.jl/latest/fit/)… and takes the type as its first input.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 20, 2023, 10:16pm UTC](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476/20 "2023-11-20T22:16:30Z")

</div>

> [@lrnv](#):
>
> since I cannot dispatch on the alias…

I might be misunderstanding something then, I was imagining something like `generatorof(::Type{Clayton}) = ClaytonGenerator` or `generatorof(::Clayton) = ClaytonGenerator`, depending on if you are passing `Clayton` itself or its instances.

[Next page](https://discourse.julialang.org/t/how-to-dispatch-on-a-type-alias/106476.md?page=2)
