# How do I define eltype for custom composite type?

**URL:** <https://discourse.julialang.org/t/how-do-i-define-eltype-for-custom-composite-type/115726>\
**Category:** General Usage\
**Created:** [June 16, 2024, 9:32pm UTC](https://discourse.julialang.org/t/how-do-i-define-eltype-for-custom-composite-type/115726 "2024-06-16T21:32:21Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![vshesh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vshesh/32/20362_2.png) [@vshesh](https://discourse.julialang.org/u/vshesh)\
**Post date:** [June 16, 2024, 9:32pm UTC](https://discourse.julialang.org/t/how-do-i-define-eltype-for-custom-composite-type/115726/1 "2024-06-16T21:32:21Z")

</div>

I tried creating my own container type alias:

```julia
Forest{Tree} = Union{<: AbstractVector{<: Tree}, <: AbstractSet{<: Tree}}

```

I want to do, in essence:

```julia
Base.eltype(::Type{Forest{T}}) where T = T 

```

```julia
julia> eltype(Forest{Int})
ERROR: UndefVarError: `T` not defined
Stacktrace:
 [1] eltype(::Type{Union{var"#s13", var"#s12"} where {var"#s13"<:(AbstractVector{<:Int64}), var"#s12"<:(AbstractSet{<:Int64})}})

```

Which I get because the Forest definition is being replaced by what it is aliased to.  
Is there a way to define the eltype for Forest specifically?

```julia
julia> Base.eltype(::Type{Union{AbstractVector{T}, AbstractSet{T}}}) where T = T
julia> eltype(Annotations.Forest{Int})
Any

```

So now it doesn’t complain but doesn’t give the right answer either …

```julia
julia> Base.eltype(::Type{Union{<: AbstractVector{<: T}, <: AbstractSet{<: T}}}) where T = T
julia> eltype(Annotations.Forest{Int})
ERROR: UndefVarError: `T` not defined
Stacktrace:
 [1] eltype(::Type{Union{var"#s13", var"#s12"} where {var"#s13"<:(AbstractVector{<:Int64}), var"#s12"<:(AbstractSet{<:Int64})}})

```

Now we’re back to the start.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [June 16, 2024, 11:15pm UTC](https://discourse.julialang.org/t/how-do-i-define-eltype-for-custom-composite-type/115726/2 "2024-06-16T23:15:23Z")

</div>

This is what you want, I guess:

```julia
julia> const Forest = Union{AbstractVector{Tree},AbstractSet{Tree}} where {Tree}
Union{AbstractSet{Tree}, AbstractVector{Tree}} where Tree

julia> Base.eltype(::Type{<:Forest{T}}) where {T} = T

julia> eltype(Forest{Int})
Int64

```

However, the `eltype` method definition above is what is termed _type piracy_, meaning that it’s not OK for production code, because neither the function (`eltype`), nor any of the type signature elements are owned by you, so such a definition wouldn’t behave well in the package ecosystem.

To avoid type piracy, perhaps define `Forest` as a `struct` instead of as a type alias.

---

<div class="post-metadata">

**Author:** ![vshesh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vshesh/32/20362_2.png) [@vshesh](https://discourse.julialang.org/u/vshesh)\
**Post date:** [June 16, 2024, 11:44pm UTC](https://discourse.julialang.org/t/how-do-i-define-eltype-for-custom-composite-type/115726/3 "2024-06-16T23:44:57Z")

</div>

Thank you.  
Yes this is just for an analysis I’m doing - won’t become production code.  
Is there a struct version of this you would recommend? I’m not sure how to use structs to represent sum types - like this?

```julia
abstract type Forest{T} end 
struct VectorForest{T} <: Forest{T}
  v::Vector{T} 
end
struct SetForest{T} <: Forest{T}
  s::Set{T}
end

```

I guess this is the “tagged union” approach but I can’t augment behavior of known data types this way. I would also have to reimplement every single function related to Vectors or Sets on my datatype if I wanted to use it as one.

I’m also curious why extending eltype to work with Unions would be considered “type piracy” - the behavior I’m generally creating here is:

```julia
given eltype(X{T}) == eltype(Y{T}) == ... == T
eltype(Union{X{T}, Y{T}, ...}) = T

```

Which seems sound to me.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [June 17, 2024, 12:00am UTC](https://discourse.julialang.org/t/how-do-i-define-eltype-for-custom-composite-type/115726/4 "2024-06-17T00:00:17Z")

</div>

> [@vshesh](#):
>
> I’m not sure how to use structs to represent sum types

Perhaps use one of the available sum type packages, e.g., SumTypes.jl.

> [@vshesh](#):
>
> I’m also curious why extending eltype to work with Unions would be considered “type piracy”

Assume type piracy were not frowned upon. In this case it might happen that variations upon your `eltype` definition could appear in several independent packages. Then it could happen, upon loading multiple of these packages, that some `eltype` calls would be ambiguous. Thus basically each package in the ecosystem could only work with a whitelisted set of packages. This would prevent the ecosystem from growing in a unified manner, instead I guess it’d be fractured into many smaller ecosystems.

---

<div class="post-metadata">

**Author:** ![screw\_dog](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/screw_dog/32/48119_2.png) [@screw\_dog](https://discourse.julialang.org/u/screw_dog)\
**Post date:** [June 17, 2024, 1:05am UTC](https://discourse.julialang.org/t/how-do-i-define-eltype-for-custom-composite-type/115726/5 "2024-06-17T01:05:09Z")

</div>

> [@nsajko](#):
>
> `const Forest = Union{AbstractVector{Tree},AbstractSet{Tree}} where {Tree}`

Just to flesh out why this is type piracy: despite using descriptive labels `Forest` and `Tree` you are actually just aliasing `AbstractVector{<:Any}` and `AbstractSet{<:Any}`. You aren’t actually defining any types that you own, just renaming existing types. So any methods of existing functions (ie `Base.eltype`) defined for `Forest` and `Tree` will be type piracy.

By defining a _new_ type called `Forest` you avoid type piracy.

ETA: the reason that you haven’t encountered any issues with this is that your `eltype` methods are pretty much exactly what Base is doing anyway. Essentially Base defines each case of the type union separately, you’re just combining them.
