# Providing {N} with type alias

**URL:** <https://discourse.julialang.org/t/providing-n-with-type-alias/104089>\
**Category:** General Usage\
**Created:** [September 21, 2023, 2:59am UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089 "2023-09-21T02:59:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jondavis847](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jondavis847](https://discourse.julialang.org/u/jondavis847)\
**Post date:** [September 21, 2023, 2:59am UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/1 "2023-09-21T02:59:09Z")

</div>

Using StaticArrays and parametric types, I can successfully produce subtyped SVectors.

```julia
using StaticArrays

abstract type A{N,T} <: StaticVector{N,T} end
@inline Base.getindex(a::A, i::Int64) = (@boundscheck checkbounds(a,i); a.data[Base.to_index(i)])

struct B{T} <: A{3,T}
    data::NTuple{3,T}
end

```

```julia
julia> B(rand(3))
3-element B{Float64} with indices SOneTo(3):
 0.8678028298561054
 0.929557303378407
 0.22910477906211102

```

However, if I do something similar through a type alias, it doesn’t work as I had hoped.

```julia
struct C{N,T} <: A{N,T}
    data::NTuple{N,T}
end

const D{T} = C{3,T}

```

```julia
julia> D(rand(3))
ERROR: DimensionMismatch: No precise constructor for D found. Length of input was 3.
Stacktrace:
 [1] _no_precise_size(SA::Type, x::Tuple{Float64, Float64, Float64})
   @ StaticArrays C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:161
 [2] construct_type(#unused#::Type{D}, x::StaticArrays.Args{Tuple{Tuple{Tuple{Float64, Float64, Float64}}}})
   @ StaticArrays C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:81
 [3] StaticArray (repeats 2 times)
   @ C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:165 [inlined]
 [4] convert
   @ C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:204 [inlined]
 [5] (D)(a::Vector{Float64})
   @ StaticArrays C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:174
 [6] top-level scope
   @ REPL[5]:1

```

Am I doing this wrong?

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [September 21, 2023, 5:11am UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/2 "2023-09-21T05:11:14Z")

</div>

I don’t understand what you goal is nor would I call your approach a “type alias”. In both cases you define new types.

If your goal is to define a variant of `StaticVector{N,T}` with `N` fixed, then I would try `const SV3 = StaticVector{3}`.

---

<div class="post-metadata">

**Author:** ![jondavis847](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jondavis847](https://discourse.julialang.org/u/jondavis847)\
**Post date:** [September 21, 2023, 1:46pm UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/3 "2023-09-21T13:46:50Z")

</div>

Hmm ok, I assumed alias was the right term here following the docs at [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#Type-Aliases). Also, because D is described as an alias of C, but I’m still learning:

```julia
julia> D
D (alias for C{3})

```

More specifically for what I’m trying to do, I have a class of vectors that all belong to A and have methods associated with A, and are all represented as SVectors. A can be broken into 2 subtypes (B and C) that still belong to A for its methods, but have their own operator overloads associated with them. B and C can further be broken down into subtypes (D,E…) that are the actual interface to the type graph (I would never create an A B or C, would just create D,E…). The trick is that while D is always length d, and E is always length e, d might not equal e. So I was hoping I could pass the size through parameters when I create D all the way up the type graph to A when it creates the SVector.

I could certainly do this by specifically defining the structs of A,B,C,D,E as I did with B above, but was wondering if aliases were appropriate here in a way that simplified the definitions in a Julian way. Something like:

```julia
using StaticArrays

struct A{N,T} <: StaticVector{N,T} 
    data::NTuple{N,T}
end
@inline Base.getindex(a::A, i::Int64) = (@boundscheck checkbounds(a,i); a.data[Base.to_index(i)])

const B{N,T} = A{N,T}
const C{N,T} = A{N,T}

const D{T} = B{3,T}
const E{T} = B{3,T}

const F{T} = C{3,T}
const G{T} = C{4,T}

```

---

<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:** [September 21, 2023, 1:59pm UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/4 "2023-09-21T13:59:29Z")

</div>

Subtyping `StaticArray` here is making this more confused because it’s adding a different codepath on the abstract type. The crux is that Julia doesn’t automatically create a constructor that fills in _some_ of the parameters:

```julia
julia> struct C{N,T}
           data::NTuple{N,T}
       end

julia> C((1,2,3))
C{3, Int64}((1, 2, 3))

julia> C{3}((1,2,3))
ERROR: MethodError: no method matching (C{3})(::Tuple{Int64, Int64, Int64})
Stacktrace:
 [1] top-level scope
   @ REPL[2]:1

julia> C{3,Int}((1,2,3))
C{3, Int64}((1, 2, 3))

```

You can define this constructor yourself:

```julia
julia> (::Type{C{N}})(d::NTuple{N,T}) where {N,T} = C{N,T}(d)

julia> C{3}((1,2,3))
C{3, Int64}((1, 2, 3))

```

---

<div class="post-metadata">

**Author:** ![jondavis847](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jondavis847](https://discourse.julialang.org/u/jondavis847)\
**Post date:** [September 21, 2023, 4:00pm UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/5 "2023-09-21T16:00:06Z")

</div>

So in the end I think I’ve gotten what I needed, and agree that I over complicated it. I’m subtyping StaticVector, but calling StaticVector directly actually produces the same error:

```julia
julia> StaticVector{6,Float64}(rand(6))
ERROR: DimensionMismatch: No precise constructor for StaticArray{Tuple{6}, Float64, 1} found. Length of input was 6.
Stacktrace:
 [1] _no_precise_size(SA::Type, x::NTuple{6, Float64})
   @ StaticArrays C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:161
 [2] construct_type(#unused#::Type{StaticArray{Tuple{6}, Float64, 1}}, x::StaticArrays.Args{Tuple{Tuple{NTuple{6, Float64}}}})
   @ StaticArrays C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:81
 [3] StaticArray (repeats 2 times)
   @ C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:165 [inlined]
 [4] convert
   @ C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:204 [inlined]
 [5] StaticArray{Tuple{6}, Float64, 1}(a::Vector{Float64})
   @ StaticArrays C:\Users\jonda\.julia\packages\StaticArrays\dTwvg\src\convert.jl:174
 [6] top-level scope
   @ REPL[11]:1

```

and so I have to define the struct with data::NTuple{X,T}, where I explicitly define X (unless I define a constructor as @mbauman recommended? more in a sec).

But my interface is typically not StaticVector{N,T}, typically we define SVector{N,T}. Changing the alias definition gets me I believe exactly what I want, and now that I’m reading back I think this is what @abraemer was recommending.

So now this works as I was hoping:

```julia
using StaticArrays

const A{N,T} = SVector{N,T}

const B{N,T} = A{N,T}
const C{N,T} = A{N,T}

const D{T} = B{3,T}
const E{T} = B{3,T}

const F{T} = C{3,T}
const G{T} = C{4,T}

f(d::D) = d.*d
f(g::G) = g + g
f2(a::A) = sqrt.(a)

```

```julia
julia> d = D([3,3,3])
3-element SVector{3, Int64} with indices SOneTo(3):
 3
 3
 3

julia> g = G([3,3,3,3])
4-element SVector{4, Int64} with indices SOneTo(4):
 3
 3
 3
 3

julia> f(d)
3-element SVector{3, Int64} with indices SOneTo(3):
 9
 9
 9

julia> f(g)
4-element SVector{4, Int64} with indices SOneTo(4):
 6
 6
 6
 6

julia> f2(d)
3-element SVector{3, Float64} with indices SOneTo(3):
 1.7320508075688772
 1.7320508075688772
 1.7320508075688772

julia> f2(g)
4-element SVector{4, Float64} with indices SOneTo(4):
 1.7320508075688772
 1.7320508075688772
 1.7320508075688772
 1.7320508075688772

```

But back on @mbauman response. I see what you’re saying about the partially filled parameters and needing to create our own constructors to cover missing parameters. I do still need the methods and behavior of SVectors on my types however, so I (maybe mistakenly?) assumed that subtyping was a must. Is there a way to maintain the behavior of SVectors in your example without subtyping?

In the end, had I wanted to use StaticVector{N,T} rather than SVector {N,T}, the constructor did solve my problem of “how do I pass N to the call for NTuple,” even while super typing.

```julia
struct H{N,T} <: StaticVector{N,T}
    data::NTuple{N,T}
end
@inline Base.getindex(A::H, i::Int64) = (@boundscheck checkbounds(A,i); A.data[Base.to_index(i)])
(::Type{H{N}})(d::NTuple{N,T}) where {N,T} = H{N,T}(d)

const H2 = H{3}

```

```julia
julia> H{3}(rand(3))
3-element H{3, Float64} with indices SOneTo(3):
 0.2669897586332304
 0.20288500609093174
 0.08817405671923229

julia> H2(rand(3))
3-element H2{Float64} with indices SOneTo(3):
 0.421901093230018
 0.6764301848959721
 0.3690068074848969

```

Thanks for the help! Trying to take the time to really understand these concepts.

---

<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:** [September 21, 2023, 4:17pm UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/6 "2023-09-21T16:17:06Z")

</div>

Why would you want to create your own type? What would it do differently from `SVector`? Just use `SVector`! 🙂

---

<div class="post-metadata">

**Author:** ![jondavis847](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jondavis847](https://discourse.julialang.org/u/jondavis847)\
**Post date:** [September 21, 2023, 4:33pm UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/7 "2023-09-21T16:33:04Z")

</div>

If for example I wanted to make a Quaternion type that is always represented as (and hopefully gains the performance of SVectors. SVector{4} \* SVector{4} is not defined, but I could define \* on the Quaternion subtype to define quat multiplication.

Of course I could just create my own type

```julia
struct Quaternion
     val::SVector{4,Float64}
end

```

and define methods operating on val, or just define some function qmult, or just use Rotations.jl in this example, but wanted to explore aliasing for more succinctly getting the functionality I’m looking for in a text book like notation.

---

<div class="post-metadata">

**Author:** ![jondavis847](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jondavis847](https://discourse.julialang.org/u/jondavis847)\
**Post date:** [September 21, 2023, 7:32pm UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/8 "2023-09-21T19:32:50Z")

</div>

Whoa, okay big misunderstanding for me. Going back to my example:

```julia
using StaticArrays

const A{N,T} = SVector{N,T}

const B{N,T} = A{N,T}
const C{N,T} = A{N,T}

const D{T} = B{3,T}
const E{T} = B{3,T}

const F{T} = C{3,T}
const G{T} = C{4,T}

f(d::T) where T<: D = T(d.*d)

```

```julia
julia> d = D([3,3,3])
3-element SVector{3, Int64} with indices SOneTo(3):
 3
 3
 3

julia> out = f(d)
3-element SVector{3, Int64} with indices SOneTo(3):
 9
 9
 9

julia> isa(out,D)
true

julia> isa(out,A)
true

julia> isa(out,F)
true

```

I’m glad out is a D and an A, but definitely don’t want it to be an F.

I think I’m officially convinced that aliasing doesn’t make sense for what I’m trying to do here, though I think I learned a lot about aliases! Thanks again for the help.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [September 21, 2023, 7:39pm UTC](https://discourse.julialang.org/t/providing-n-with-type-alias/104089/9 "2023-09-21T19:39:09Z")

</div>

I’m not sure it’s been said explicitly, but “alias” in the printing you’ve shown earlier in the thread doesn’t mean “a new type that behaves just like this other type” (which is what I think haskell gives you with one of its type declarations?), but “this is egal to this other thing”. In other words, `const Foo{N} = Bar{Int,N}` means that `Foo` is not a new type, but _exactly_ the same as if you’d write `Bar{Int,N}` (with appropriate values for `N`) everywhere.
