I need to work with a set of points that might each have a different type. Consider as a rough example:

```
abstract type AbstractLabel end
struct LabelA <: AbstractLabel end
struct LabelB <: AbstractLabel end
struct LabelC <: AbstractLabel end
struct PointWithLabel{L<:AbstractLabel}
xy::Vector{Float64}
label::Type{L}
PointWithLabel(x::Float64, y::Float64, label::Type{L}) where {L} = new{L}([x, y], label)
PointWithLabel(x, y, label) = PointWithLabel(Float64(x), Float64(y), label)
PointWithLabel{L}(x, y) where {L} = PointWithLabel(x, y, L)
end
const PointA = PointWithLabel{LabelA}
const PointB = PointWithLabel{LabelB}
const PointC = PointWithLabel{LabelC}
```

I could then define for example the vector

```
p1 = PointA(0.5, 0.3)
p2 = PointB(0.17, -0.3)
p3 = PointC(0.0, 0.0)
p4 = PointB(0.2, 0.5)
vec1 = [p1, p2, p3, p4]
```

```
4-element Vector{PointWithLabel}:
PointA([0.5, 0.3], LabelA)
PointB([0.17, -0.3], LabelB)
PointC([0.0, 0.0], LabelC)
PointB([0.2, 0.5], LabelB)
```

Alternatively, I could define the vector as

```
vec2 = Vector{PointWithLabel{L} where L}([p1, p2, p3, p4])
```

```
4-element Vector{PointWithLabel{L} where L}:
PointA([0.5, 0.3], LabelA)
PointB([0.17, -0.3], LabelB)
PointC([0.0, 0.0], LabelC)
PointB([0.2, 0.5], LabelB)
```

**Which of these vectors would be better to work with for performance**? Iâ€™ll be e.g. solving differential equations with many thousands of these types of points, and using the labels in the type of the point to exploit multiple dispatch for defining new addition formulas (e.g. `+(::PointA, ::PointB)`

and `+(::PointC, ::PointA)`

). I initially thought `vec1`

would be better since the element type is not concrete, `!isconcretetype(PointWithLabel)`

, although `vec2`

requires me to define methods specific for the type `PointWithLabel{L} where L`

. Alternatively, I could work with a `Vector{Union{PointA, PointB, PointC}}`

, but I remember from somewhere (I think) that unions are not always performant.