# Get array type (e.g. Array, CuArray, etc.) from concrete array

**URL:** <https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516>\
**Category:** General Usage\
**Created:** [August 9, 2022, 3:08am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516 "2022-08-09T03:08:21Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![torrance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torrance/32/38990_2.png) [@torrance](https://discourse.julialang.org/u/torrance)\
**Post date:** [August 9, 2022, 3:08am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/1 "2022-08-09T03:08:21Z")

</div>

This should be easy, but I haven’t found a way to do it.

I want a function that takes some concrete array type (\<: AbstractArray), that might be backed by Array, or CuArray, or ROCArray or whatever, and returns the unparameterised constructor. e.g.

```
arraytype(::Array{T, N}) -> Array

```

or

```
arraytype(::CuArray{T, N}) -> CuArray

```

I want to do this in a way that doesn’t require knowing, ahead of time, the concrete array types.

Something like:

```
function arraytype(::A{T, N}) where {T <: Type, N <: Int, A <: AbstractArray}
    return A
end

```

(Which isn’t legal code: `TypeError: in Type{...} expression, expected UnionAll, got a value of type TypeVar`)

Is something like this possible?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 9, 2022, 3:41am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/2 "2022-08-09T03:41:53Z")

</div>

```julia
julia> a
3-element Vector{Int64}:
 1
 2
 3

julia> typeof(a).name.wrapper
Array

```

---

<div class="post-metadata">

**Author:** ![torrance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torrance/32/38990_2.png) [@torrance](https://discourse.julialang.org/u/torrance)\
**Post date:** [August 9, 2022, 3:56am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/3 "2022-08-09T03:56:45Z")

</div>

Thanks, seems to work! I thought this kind of runtime reflection would introduce type instability but that doesn’t seem to be the case (?).

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [August 9, 2022, 4:03am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/4 "2022-08-09T04:03:00Z")

</div>

Note that unless you can find about `datatype.name.wrapper` in the Julia documentation, this is an implementation detail and can break with any Julia version (including a patch one). I am not sure there is a generic and safe way to do this.

---

<div class="post-metadata">

**Author:** ![torrance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torrance/32/38990_2.png) [@torrance](https://discourse.julialang.org/u/torrance)\
**Post date:** [August 9, 2022, 4:09am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/5 "2022-08-09T04:09:00Z")

</div>

Yeah right - good point. Unmarking it as a solution for now then.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 9, 2022, 4:49am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/6 "2022-08-09T04:49:10Z")

</div>

Do you have a clear idea what you will use this for, and could this be an xy-problem?

---

<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:** [August 9, 2022, 5:03am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/7 "2022-08-09T05:03:09Z")

</div>

Most cases of people asking for this are covered by `similar`.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 9, 2022, 5:15am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/8 "2022-08-09T05:15:27Z")

</div>

> [@torrance](#):
>
> ```julia
> function arraytype(::A{T, N}) where {T <: Type, N <: Int, A <: AbstractArray}
> return A
> end
> 
> ```

Even though this function will not work either way, there are some extra problems with it.

Let’s take an example: `Array{Float64, 2}`, so that `T` is `Float64`, and `N` is `2`. Note that

```julia
julia> Float64 <: Type
false

julia> 2 <: Int
ERROR: TypeError: in <:, expected Type, got a value of type Int64

```

The type parameters are not in that kind of subtype relationship. Instead they are in an `isa` relationship:

```julia
julia> Float64 isa Type
true

julia> 2 isa Int
true

```

This one, however, is correct:

```julia
julia> Array <: AbstractArray
true

```

So you are not using the type constraints correctly; the correct way is

```julia
arraytype(::A{T, N}) where {T <: Any, N, A <: AbstractArray}

```

The constraint on `T` must be in the type hierarchy of `Float64` (and `Type` isn’t):

```julia
julia> supertypes(Float64)
(Float64, AbstractFloat, Real, Number, Any)

```

And `2` has no type hierarchy at all:

```julia
julia> supertypes(2)
ERROR: MethodError: no method matching supertypes(::Int64)

```

This is why you always see `N` unconstrained in functions that take arrays.

---

<div class="post-metadata">

**Author:** ![torrance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torrance/32/38990_2.png) [@torrance](https://discourse.julialang.org/u/torrance)\
**Post date:** [August 9, 2022, 5:19am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/9 "2022-08-09T05:19:07Z")

</div>

@DNF There are times when you need to replace the underlying storage of an array based on some runtime configuration.

In my case, this comes down to the tricky business of writing code that is generic for CPU/CUDA/ROCM/(ONEAPI?). I am aiming to do this in a type stable way, and using the input types to signal which device should be doing the computing. This is usually straightforward, and I do use `similar()` a lot (as previous commenter mentioned).

However, oftentimes the array wrapper can make this fairly elegant, e.g. I might need to provision some data first on the host, then send to the device: `data_device = wrapper(data)` where `wrapper = Array | CuAray | ROCArray`. Or similarly, I use `StructArrays` which includes the method `replace_storage(CuArray, mystructarray)`, and this also needs the array wrapper type.

One could pass the wrapper around as an argument to all functions, but this seems a little yucky.

Essentially, this is about managing runtime array storage in a way that propagates through my program in a type stable way. Definitely open to ideas about how other people have manged this.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 9, 2022, 5:26am UTC](https://discourse.julialang.org/t/get-array-type-e-g-array-cuarray-etc-from-concrete-array/85516/10 "2022-08-09T05:26:19Z")

</div>

Thanks for the explanation, but perhaps this would be clearer if you could show a usage example?
