# Weird Tuple types that seem like they should be disallowed?

**URL:** https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080
**Category:** New to Julia
**Tags:** question, type, tuple, parametric-types
**Created:** [March 13, 2021, 3:44pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080 "2021-03-13T15:44:13Z")
**Posts on this page:** 12
**Page:** 1

<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: [March 13, 2021, 3:44pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/1 "2021-03-13T15:44:13Z")

</div>

I noticed that some Tuple types that are parameterized by non-types exist, but seem useless. I wonder if they:

1. May have instances at all?

2. Should be disallowed?

Example:

```julia
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.5.4 (2021-03-11)
 _/ |\ __'_|_|_|\__'_| |
|__/ |

julia> Tuple{1243} <: Tuple{Any}
true

julia> Tuple{(124310, 983724)} <: Tuple{Any}
true

```

It’s relevant that similar constructions are not permissible in function type signatures:

```julia
julia> function f(x::423)
       5
       end
ERROR: ArgumentError: invalid type for argument x in method definition for f at REPL[2]:1
Stacktrace:
 [1] top-level scope at REPL[2]:1
 [2] run_repl(::REPL.AbstractREPL, ::Any) at /build/julia/src/julia-1.5.4/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288

```

---

<div class="post-metadata">

### Author: ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)
#### Post date: [March 13, 2021, 3:59pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/2 "2021-03-13T15:59:28Z")

</div>

Good observation! It actually can be really useful to put data up in the type-domain. The simplest example is probably multidimensional arrays; in Julia, they are represented by the `AbstractArray{T, N}` type, where `N` is an integer representing the number of dimensions, i.e. `Matrix{Float64} === Array{Float64, 2}`. Note that it’s not the type `Integer`, but the literal number 2.

As a more complicated example, I wrote a [blog post](https://ericphanson.com/blog/2019/another-example-of-using-type-domain-information-in-julia/) about encoding a permutation as part of a type to permute vectors very quickly (at the cost of recompiling the function whenever you change the permutation).

Having values as part of types is mentioned in the [docs](https://docs.julialang.org/en/v1/manual/types/) too,

> - Both abstract and concrete types can be parameterized by other types. They can also be parameterized by symbols, by values of any type for which [`isbits`](https://docs.julialang.org/en/v1/base/base/#Base.isbits) returns true (essentially, things like numbers and bools that are stored like C types or `struct` s with no pointers to other objects), and also by tuples thereof. Type parameters may be omitted when they do not need to be referenced or restricted.

To answer your question,

> May have instances at all?

I think the answer is no. But that doesn’t mean they can’t be used, e.g.

```julia
julia> struct MyType{T} end

julia> f(::Type{MyType{T}}) where T = T[1] + 1
f (generic function with 1 method)

julia> X = MyType{(5,6,7)}
MyType{(5, 6, 7)}

julia> f(X)
6

```

By the way, the result here is actually computed at compile-time, e.g. in

```julia
julia> @code_warntype f(X)
Variables
  #self#::Core.Const(f)
  #unused#::Core.Const(MyType{(5, 6, 7)})

Body::Int64
1 ─ %1 = Base.getindex($(Expr(:static_parameter, 1)), 1)::Core.Const(5)
│ %2 = (%1 + 1)::Core.Const(6)
└── return %2

```

we can see the `Core.Const(6)` result is known to the compiler to be a constant.

Lastly, just to comment on

> Should be disallowed?

Generally Julia tries to not impose restrictions on users unless they are needed for performance or correctness, so I think even if they weren’t so fundamental as to be used in `Array`, they should not be disallowed.

---

<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: [March 13, 2021, 4:03pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/3 "2021-03-13T16:03:13Z")

</div>

Hmm, you seem to have misunderstood me somewhat: I do know about parametric types and singleton types (and, yes, singleton types can have instances, just do, e.g., `MyType{(5, 6, 7)}()`, notice the parentheses at the end).  
But I was asking specifically about the `Tuple` types that are parameterized by non-types 😃

---

<div class="post-metadata">

### Author: ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)
#### Post date: [March 13, 2021, 4:06pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/4 "2021-03-13T16:06:04Z")

</div>

Hm, I guess I don’t really see the distinction, it just looks like another way to put data in the type domain. E.g.

```julia
julia> g(::Type{Tuple{T}}) where {T} = T - 1
g (generic function with 1 method)

julia> g(Tuple{123})
122

```

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [March 13, 2021, 4:11pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/5 "2021-03-13T16:11:15Z")

</div>

> [@nsajko](#):
>
> But I was asking specifically about the `Tuple` types that are parameterized by non-types

Aren’t StaticArrays implemented like that?

---

<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: [March 13, 2021, 4:13pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/6 "2021-03-13T16:13:30Z")

</div>

Eric, you’re technically correct, but the usage like yours is not really “blessed” by the Julia devs, it seems: the Julia Manual section on Types says this:

> For consistency across Julia, the call site should always pass a `Val` _instance_ rather than using a _type_, i.e., use `foo(Val(:bar))` rather than `foo(Val{:bar})`.

I.e., the blessed way is to pass instances of singleton types to functions instead of the singleton types themselves.

---

<div class="post-metadata">

### Author: ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)
#### Post date: [March 13, 2021, 4:13pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/7 "2021-03-13T16:13:32Z")

</div>

> [@lmiq](#):
>
> Aren’t StaticArrays implemented like that?

Yep! They put the size as a tuple in the type: [https://github.com/JuliaArrays/StaticArrays.jl/blob/59f92e0ca7ac391a850a6e7a2ce1eb53aa237fc4/src/StaticArrays.jl#L73-L77](https://github.com/JuliaArrays/StaticArrays.jl/blob/59f92e0ca7ac391a850a6e7a2ce1eb53aa237fc4/src/StaticArrays.jl#L73-L77). Great example.

---

<div class="post-metadata">

### Author: ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)
#### Post date: [March 13, 2021, 4:16pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/8 "2021-03-13T16:16:12Z")

</div>

True, although I think that’s more of a style issue than anything else, but I could be mistaken. I guess the StaticArrays example gives a better-motivated reason than singleton types.

---

<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: [March 13, 2021, 4:17pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/9 "2021-03-13T16:17:37Z")

</div>

I definitely agree that the StaticArrays way is less verbose, but I guess the developers had some good reason for writing the quoted paragraph in the manual, so probably that code should be somewhat adjusted in StaticArrays?

---

<div class="post-metadata">

### Author: ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)
#### Post date: [March 13, 2021, 4:19pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/10 "2021-03-13T16:19:10Z")

</div>

I think the StaticArrays example is a different usage than what they’re discussing at that part of the manual, since the StaticArrays subtypes generally store data in fields in addition to keeping the size as a tuple in the type. For example, here: [StaticArrays.jl/SArray.jl at 59f92e0ca7ac391a850a6e7a2ce1eb53aa237fc4 · JuliaArrays/StaticArrays.jl · GitHub](https://github.com/JuliaArrays/StaticArrays.jl/blob/59f92e0ca7ac391a850a6e7a2ce1eb53aa237fc4/src/SArray.jl#L18-L30) is where the `SArray` type is defined (`SArray` is analogous to `Array`, while `StaticArray` is analogous to `AbstractArray`).

---

<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: [March 13, 2021, 4:28pm UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/11 "2021-03-13T16:28:16Z")

</div>

I found the commit that introduced that paragraph to the manual: [Use Val(x) and f(::Val{x}) (#22475) · JuliaLang/julia@259996c · GitHub](https://github.com/JuliaLang/julia/commit/259996c07e87fc3d2da8f05d4dfa405cdf45fbbe)

The commit message presents the following advantage, but I’m not sure if it applies here:

> This form also has the advantage that multiple singleton instances can be put in a tuple and inference will work (similarly with multiple-return functions).

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 14, 2021, 9:14am UTC](https://discourse.julialang.org/t/weird-tuple-types-that-seem-like-they-should-be-disallowed/57080/12 "2021-03-14T09:14:45Z")

</div>

> [@nsajko](#):
>
> I guess the developers had some good reason for writing the quoted paragraph in the manual, so probably that code should be somewhat adjusted in StaticArrays

It is a hack, and this is known. Cf

> <https://github.com/JuliaArrays/StaticArrays.jl/issues/807>
>
> \`StaticArray\` uses \`Tuple{1,2,3}\` to encode the size:
> 
> https://github.com/Juli…aArrays/StaticArrays.jl/blob/cee335d3e7f08dcc72075ac5f18bb3a632e8b841/src/StaticArrays.jl#L73-L76
> 
> Arguably, the type parameters of \`Tuple\` should be types. Otherwise, such \`Tuple\` does not have an instance. It also confuses some users (including me when I first saw this): \[What does Tuple{3} mean in StaticArrays? - Usage / First steps - JuliaLang\](https://discourse.julialang.org/t/what-does-tuple-3-mean-in-staticarrays/32774).
> 
> A better solution may be to use \`Tuple{StaticInteger{1},StaticInteger{2},StaticInteger{3}}\` instead of \`Tuple{1,2,3}\`. For example, a possible implementation of \`SArray\` would be
> 
> \`\`\`julia
> struct SArray{N, S \<: NTuple{N,StaticInteger}, T, L} \<: StaticArray{S, T, N}
> data::NTuple{L,T}
> size::S
> end
> 
> const SVector{S, T} = SArray{1, Tuple{StaticInteger{S}}, T, S}
> const SMatrix{S1, S2, T, L} = SArray{2, Tuple{StaticInteger{S1}, StaticInteger{S2}}, T, L}
> \`\`\`
> 
> (Early discussion in https://github.com/JuliaArrays/StaticArrays.jl/issues/806#issuecomment-655279036)

> [@nsajko](#):
>
> the blessed way is

Perhaps you are confusing Julia with some kind of religion (it isn’t — it is a programming language).

The manual is suggesting a way to do something above, but as pointed out above by @ericphanson, these remain valid type parameters. And no, not all types need to have instances. That’s perfectly fine.
