# Function property differs based on the position of the generic type

**URL:** <https://discourse.julialang.org/t/function-property-differs-based-on-the-position-of-the-generic-type/119340>\
**Category:** General Usage\
**Tags:** parametric-types, functions\
**Created:** [September 12, 2024, 4:50pm UTC](https://discourse.julialang.org/t/function-property-differs-based-on-the-position-of-the-generic-type/119340 "2024-09-12T16:50:27Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![akrishnamoorthy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/akrishnamoorthy/32/46563_2.png) [@akrishnamoorthy](https://discourse.julialang.org/u/akrishnamoorthy)\
**Post date:** [September 12, 2024, 4:50pm UTC](https://discourse.julialang.org/t/function-property-differs-based-on-the-position-of-the-generic-type/119340/1 "2024-09-12T16:50:27Z")

</div>

Let

```julia
julia> using LinearAlgebra

julia> id(X,T) = T(Matrix{eltype(X)}(I, size(X)...))
id (generic function with 1 method)

julia> A = complex.(randn(2,2),randn(2,2));

julia> typeof(transpose(id(A,Hermitian)))
Transpose{ComplexF64, Hermitian{ComplexF64, Matrix{ComplexF64}}}

```

Now, we define two functions as follows:

```julia
julia> f(A::Transpose{T,Hermitian{T,M}}) where {T,M <: StridedMatrix} = 1
f (generic function with 1 method)
julia> methods(f)
# 1 method for generic function "f" from Main:
 [1] f(A::Transpose{T, Hermitian{T, M}}) where {T, M<:(StridedMatrix{T} where T)}
     @ REPL[5]:1

julia> g(A::Transpose{T,Hermitian{T, <:StridedMatrix}}) where {T} = 1
g (generic function with 1 method)
julia> methods(g)
# 1 method for generic function "g" from Main:
 [1] g(A::Transpose{T, Hermitian{T, <:StridedMatrix{T} where T}}) where T
     @ REPL[7]:1

```

I would expect both functions to accept a variable of type `transpose(id(A,Hermitian))`. However, `f` works and `g` does not!

```julia
julia> f(transpose(id(A,Hermitian)))
1

julia> g(transpose(id(A,Hermitian)))
ERROR: MethodError: no method matching g(::Transpose{ComplexF64, Hermitian{ComplexF64, Matrix{ComplexF64}}})

Closest candidates are:
  g(::Transpose{T, Hermitian{T, <:StridedMatrix{T} where T}}) where T
   @ Main REPL[7]:1

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

```

Could someone please explain why this is the case? That is, why must `M` be explicitly declared here although the method signatures seem equivalent.

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [September 12, 2024, 5:58pm UTC](https://discourse.julialang.org/t/function-property-differs-based-on-the-position-of-the-generic-type/119340/2 "2024-09-12T17:58:53Z")

</div>

You need a `<:` before `Hermitian`:

```julia
g(A::Transpose{T,<:Hermitian{T, <:StridedMatrix}}) where {T} = 1

```

With `Transpose{T, Hermitian{T, <:StridedMatrix}} where T` (without the `<:`), it’s analogous to how `Vector{Any}` is a concrete type, and `[1, 2, 3] isa Vector{Any}` is `false`.

---

<div class="post-metadata">

**Author:** ![akrishnamoorthy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/akrishnamoorthy/32/46563_2.png) [@akrishnamoorthy](https://discourse.julialang.org/u/akrishnamoorthy)\
**Post date:** [September 12, 2024, 6:08pm UTC](https://discourse.julialang.org/t/function-property-differs-based-on-the-position-of-the-generic-type/119340/3 "2024-09-12T18:08:58Z")

</div>

Thank you for the explanation! Based on your response, I’m guessing that using `M` or `<:` again transforms it analogous to

```julia
julia> [1,2,3] isa Vector{Any}
false

julia> [1,2,3] isa Vector{<:Any}
true

julia> [1,2,3] isa Vector{T} where {T<:Any}
true

```

The mistake in my thinking was that I expected `Transpose{T,Hermitian{T, <:StridedMatrix}}` to be generic because of the `<:StridedMatrix`. But, I guess every level of a nested type needs `<:` to remain generic.
