# Shouldn't HasShape trait subtype HasLength?

**URL:** <https://discourse.julialang.org/t/shouldnt-hasshape-trait-subtype-haslength/6400>\
**Category:** Internals & Design\
**Tags:** design, traits\
**Created:** [October 12, 2017, 12:12am UTC](https://discourse.julialang.org/t/shouldnt-hasshape-trait-subtype-haslength/6400 "2017-10-12T00:12:36Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alexander\_Belopolsky](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alexander_belopolsky/32/4882_2.png) [@Alexander\_Belopolsky](https://discourse.julialang.org/u/Alexander_Belopolsky)\
**Post date:** [October 12, 2017, 12:12am UTC](https://discourse.julialang.org/t/shouldnt-hasshape-trait-subtype-haslength/6400/1 "2017-10-12T00:12:36Z")

</div>

The `HasLength` and `HasShape` generator traits are defined as follows

- `HasLength()` if there is a fixed, finite length.
- `HasShape()` if there is a known length plus a notion of multidimensional shape (as for an array).

This suggests that any method that can accept a `HasLength` generator should be able to deal with a ` HasShape` one as well. However since these traits make a [flat hierarchy](https://github.com/JuliaLang/julia/blob/4247bbafe650930b9f6da4feecf0a7dcc37e5204/base/generator.jl#L51), a method defined as

```julia
f(::HasLength, iter) = ..

```

would not accept e.g. an array.

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [October 12, 2017, 3:49am UTC](https://discourse.julialang.org/t/shouldnt-hasshape-trait-subtype-haslength/6400/2 "2017-10-12T03:49:08Z")

</div>

The way things are currently set up, with the convention that methods should be written

```julia
f(::HasLength, iter) = ..

```

and not

```julia
f(::Type{HasLength}, iter) = ..

```

(as you had it before your edit), both `HasLength` and `HasShape` need to be instantiable, and hence need to be concrete types. Julia doesn’t allow inheritance from concrete types, so `HasShape` can’t subtype `HasLength`.

I do think that this would be possible if the convention were to use methods of the latter form above, and to have `HasLength`, `HasShape` etc. all be abstract types. I’m not sure why the former form was chosen.

Do note that you can currently always do

```julia
f(::Union{HasLength, HasShape}, iter) = ..

```

(as is often done in practice), which I suppose isn’t that much worse than

```julia
f(::Type{<:HasLength}, iter) = ..

```

with a hypothetical abstract `HasShape` and `HasShape <: HasLength`.
