# Help with subtyping semantics

**URL:** <https://discourse.julialang.org/t/help-with-subtyping-semantics/126986>\
**Category:** General Usage\
**Created:** [March 15, 2025, 3:09pm UTC](https://discourse.julialang.org/t/help-with-subtyping-semantics/126986 "2025-03-15T15:09:17Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [March 15, 2025, 3:09pm UTC](https://discourse.julialang.org/t/help-with-subtyping-semantics/126986/1 "2025-03-15T15:09:17Z")

</div>

I’m trying to build a type hierarchy around different kinds of units. So far I have this working:

```julia
abstract type AbstractUnits{D} end
abstract type AbstractAffineUnits{D} <: AbstractUnits{D} end 
abstract type AbstractScalarUnits{D} <: AbstractAffineUnits{D} end

```

which is quite straightforward. However, I’m trying to tell the compiler that an  
`AbstractDimension{P}` is a subtype of `AbstractScalarUnits{D}` as long as `D` is a supertype of `AbstractDimension{P}`. Something like

```julia
abstract type AbstractDimensions{P} <: AbstractScalarUnits{AbstractDimensions{P}} end

```

I was actually surprised that this code ran, but the results are a bit unintuitive:

```julia
julia> Dimensions <: AbstractScalarUnits
true #Makes sense
julia> Dimensions <: AbstractScalarUnits{AbstractDimensions}
false #Doesn't make sense
julia> Dimensions{Int} <: AbstractScalarUnits{Dimensions{Int}}
false #Doesn't make sense

```

Is there some way to make the type system work for this use case? Or do I have to just define an AbstractDimension, and a constant that is a union of “AbstractScalarUnits” and “AbstractDimension”

---

<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:** [March 15, 2025, 4:42pm UTC](https://discourse.julialang.org/t/help-with-subtyping-semantics/126986/2 "2025-03-15T16:42:34Z")

</div>

> [@Deduction42](#):
>
> `AbstractDimension{P}` is a subtype of `AbstractScalarUnits{D}` as long as `D` is a supertype of `AbstractDimension{P}`

In Julia syntax, `AbstractDimension{P}<:D && AbstractDimension{P}<:AbstractScalarUnits{D}`. That’s not what your `AbstractDimensions{P}` definition describes, and you can’t define a type with multiple supertypes or with a bound that needs the type to already exist.

> [@Deduction42](#):
>
> ```julia
> julia> Dimensions{Int} <: AbstractScalarUnits{Dimensions{Int}}
> false #Doesn't make sense
> 
> ```

Explaining this would require you to provide the `Dimensions` definition, but assuming it’s a straightforward `Dimensions{T} <: AbstractDimensions{T}`, then `Dimensions{Int} <: AbstractScalarUnits{AbstractDimensions{Int}}`. Type parameters are only covariant for `Tuple`, in other words `AbstractScalarUnits{Dimensions{Int}}` does not subtype `AbstractScalarUnits{AbstractDimensions{Int}}` and was unrelated to `Dimensions{Int}`.

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [March 15, 2025, 5:09pm UTC](https://discourse.julialang.org/t/help-with-subtyping-semantics/126986/3 "2025-03-15T17:09:06Z")

</div>

Shoot, I forgot to include my Dimension definition:

```julia
@kwdef struct Dimensions{P} <: AbstractDimensions{P}
    length::P = 0
    mass::P = 0
    time::P = 0
    current::P = 0
    temperature::P = 0
    luminosity::P = 0
    amount::P = 0
end

```

I also just realized that what I was attempting to do was to trying to define:

```julia
AbstractQuantity{T} <: T

```

so that

```julia
Quantity{<:Number} <: Number
Quantity{<:AbstractArray} <: AbstractArray

```

It appears that Unitful.jl simply defines

```julia
abstract type AbstractQuantity{T,D,U} <: Number end

```

and leaves it at that, so all AbstractQuantities need to be "Number"s. By contrast, DynamicQuantities defines a whole slew of quantity types, essentially making a parallel hierarchy to tie into Julia’s type system

```julia
abstract type AbstractQuantity{T,D} <: Number end
abstract type AbstractGenericQuantity{T,D} end
abstract type AbstractRealQuantity{T,D} <: Real end
struct QuantityArray{T,N,D<:AbstractDimensions,Q<:UnionAbstractQuantity{T,D},V<:AbstractArray{T,N}} <: AbstractArray{Q,N} ....

```

While this looks horrendous, the upside is that if someone else has algorithms specified to work for `<:Number` or `AbstractArray{<:Number}`, these objects would just work as long as you define all the basic functions for `\<:Number’. The downside is that you have to define every function for each of these types or use the mother of all type-unions (which risks ambiguities). I wonder if the Holy Traits pattern could help with this.
