# How to subtype a type alias?

**URL:** <https://discourse.julialang.org/t/how-to-subtype-a-type-alias/24050>\
**Category:** General Usage\
**Tags:** traits\
**Created:** [May 9, 2019, 9:49pm UTC](https://discourse.julialang.org/t/how-to-subtype-a-type-alias/24050 "2019-05-09T21:49:05Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [May 10, 2019, 6:49pm UTC](https://discourse.julialang.org/t/how-to-subtype-a-type-alias/24050/4 "2019-05-10T18:49:44Z")

</div>

> Is it possible to create a supertype to the trait somehow?

A trait already is _like_ a supertype. So in the example I showed above, we have the trait `IsMyArray{T}` and we can add members to it by just adding methods to the `ismyarray` function.

I still find your example quite unclear, and from what you say I suspect you can get away with something much simpler, but I’m going to assume the actual functionality you need is something like an abstract type. In that case, I’ll try again to give an example that might answer your question using traits.

First, lets define our types and aliases:

```julia
struct Bulk end

struct MyType
    data::Float64
end

const MultiLayer = Vector{MyType}

```

Now, lets define a trait called `Structure`, and make a function `has_structure_trait` that can decide if a given type is a member of our trait. For now, we’ll only register `Bulk` and `MultiLayer` as members, but we can add more whenever we like.

```julia
struct Structure{T} end
struct Not{T} end 

has_structure_trait(::T) where {T} = Not{Structure{T}}()
has_structure_trait(::MultiLayer) = Structure{MultiLayer}()
has_structure_trait(::Bulk) = Structure{Bulk}()

```

Now we can define our functions. The main difference from regular dispatch rules is that we’ll need functions that send their input to `has_structure_trait` to decide if they’re kosher to dispatch on:

```julia
absorption(structure) = absorption(has_structure_trait(structure), structure)
function absorption(::Structure{T}, structure) where {T}
    r= reflection(structure)
    t= transmission(structure)
   return 1-r-t
end

reflection(s) = reflection(has_structure_trait(s), s)
reflection(::Structure{Bulk}, s::Bulk) = 0.1
reflection(::Structure{MultiLayer}, s::MultiLayer) = sum(x -> (x.data), s)

transmission(s) = transmission(has_structure_trait(s), s)
transmission(::Structure{Bulk}, s::Bulk) = 0.2
transmission(::Structure{MultiLayer}, s::MultiLayer) = sum(x -> 2*(x.data), s)

```

Now lets test it at the REPL.

```julia
julia> absorption(Bulk())
0.7

julia> absorption([MyType(0.1), MyType(0.2)])
0.09999999999999987

julia> absorption([1, 2])
ERROR: MethodError: no method matching absorption(::Not{HasStructureTrait{Array{Int64,1}}}, ::Array{Int64,1})
Closest candidates are:
  absorption(::HasStructureTrait{T}, ::T) where T at REPL[10]:2
  absorption(::Any) at REPL[9]:1
Stacktrace:
 [1] absorption(::Array{Int64,1}) at ./REPL[9]:1
 [2] top-level scope at none:0

```

If we want to improve that error message, we can do this:

```julia
julia> absorption(::Not{Structure{T}}, x::T) where {T} = throw("$T does not have the Structure Trait.")
absorption (generic function with 4 methods)

julia> absorption([1,2])
ERROR: "Array{Int64,1} does not have the Structure Trait."
Stacktrace:
 [1] absorption(::Not{HasStructureTrait{Array{Int64,1}}}, ::Array{Int64,1}) at ./REPL[19]:1
 [2] absorption(::Array{Int64,1}) at ./REPL[9]:1
 [3] top-level scope at none:0

```

* * *

So what we’ve done is made a trait called `Structure{T}` and we can add members to it using the `has_structure_trait` function. That can be done at any time and is very extensible. It is analogous to defining an abstract type, except it has fewer restrictions, and we can even do it to types we don’t own.

The downside is that we have to introduce methods like

```julia
absorption(structure) = absorption(has_structure_trait(structure), structure)

```

which decide if a certain structure gets passed on to

```julia
absorption(::Structure{T}, structure::T) where {T}

```

and this can add a fair amount of verbosity as you can see.

Basically the way to think about traits is that we are hacking the dispatch system so that we can just write a function `has_structure_trait` which decides what method gets used on a certain piece of data instead of the normal rules from the type system.

* * *

**Edits:**  
I’ve included some clarity improvements and the suggestion from @Tamas_Papp to dispatch on values instead of types.

---

_[View the full topic](https://discourse.julialang.org/t/how-to-subtype-a-type-alias/24050)._
