# Functions of tuples of matrices VS Functions of vectors of tuples of matrices

**URL:** <https://discourse.julialang.org/t/functions-of-tuples-of-matrices-vs-functions-of-vectors-of-tuples-of-matrices/104022>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [September 19, 2023, 12:33pm UTC](https://discourse.julialang.org/t/functions-of-tuples-of-matrices-vs-functions-of-vectors-of-tuples-of-matrices/104022 "2023-09-19T12:33:03Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![arnerob](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/arnerob/32/49522_2.png) [@arnerob](https://discourse.julialang.org/u/arnerob)\
**Post date:** [September 19, 2023, 12:33pm UTC](https://discourse.julialang.org/t/functions-of-tuples-of-matrices-vs-functions-of-vectors-of-tuples-of-matrices/104022/1 "2023-09-19T12:33:03Z")

</div>

I get a MethodError in my code and I’m trying to understand the behaviour. Functions of tuples of matrices work and functions of vectors of tuples of matrices give a MethodError. A minimum working example would be the following:

```julia
julia> A=([[1,2] [3,4]], [[5,6] [7,8]])
([1 3; 2 4], [5 7; 6 8])

julia> function f(P::Tuple{Matrix, Matrix}) return P[1]+P[2] end
f (generic function with 1 method)

julia> f(A)
2×2 Matrix{Int64}:
 6 10
 8 12

julia> function f(P::Vector{Tuple{Matrix, Matrix}}) return [Q[1]+Q[2] for Q in P] end
f (generic function with 2 methods)

julia> f([A])
ERROR: MethodError: no method matching f(::Vector{Tuple{Matrix{Int64}, Matrix{Int64}}})

Closest candidates are:
  f(::Tuple{Matrix, Matrix})
   @ Main REPL[3]:1
  f(::Vector{Tuple{Matrix, Matrix}})
   @ Main REPL[5]:1

Stacktrace:
 [1] top-level scope
   @ REPL[6]:1

```

I fixed this as follows:

```julia
julia> function g(P::Vector{Tuple{Matrix{T}, Matrix{T}}}) where T return [Q[1]+Q[2] for Q in P] end
g (generic function with 1 method)

julia> g([A])
1-element Vector{Matrix{Int64}}:
 [6 10; 8 12]

```

To avoid getting this error in the future, my question is why the first thing doesn’t work and the second thing does and in what cases I will encounter this.

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [September 19, 2023, 1:05pm UTC](https://discourse.julialang.org/t/functions-of-tuples-of-matrices-vs-functions-of-vectors-of-tuples-of-matrices/104022/2 "2023-09-19T13:05:47Z")

</div>

The first thing works, because `Tuple` is a bit of a special type. In particular, its parameters are not _invariant_ (see here for more explanations: [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#Tuple-Types) ).

For any parametric type `T` that is not `Tuple` (or `Union` – I think these two are the only exceptions?), this is the behavior:

```julia
julia> Int <: Integer
true

julia> Array{Int} <: Array{Integer}
false

```

But for `Tuple`, we have

```julia
julia> Tuple{Int} <: Tuple{Integer}
true

```

Since the type of your variable `A` is

```julia
julia> typeof(A)
Tuple{Matrix{Int64}, Matrix{Int64}}

```

the concrete tuple type is a subtypes of the abstract one, but wrapped in the `Array` or any other type, that breaks:

```julia
julia> typeof(A) <: Tuple{Matrix, Matrix}
true

julia> Array{typeof(A)} <: Array{Tuple{Matrix, Matrix}}
false

```

Long story short: That it doesn’t work is the default – `Tuple` is the exception. If you find that it’s often too verbose to annotate the type parameters like in your example, you could try to just remove the argument type annotation (if you don’t need it for dispatch). If it’s not clear what the function argument needs to be then, perhaps a custom struct might help.
