Function definition with parametric types

Hello,

It’s a basic question, but it’s still unclear to me.
What are the functional differences between the function definitions below?

struct A{T}
end

func(a::A) = #code
func(a<:A) = #code

func(a::A{T}) where {T} = #code
func(a<:A{T}) where {T} = #code

func(a::Type{A}) = #code
func(a::Type{<:A}) = #code

Thank you for clearing that up!

# defined parametric type is abstract, an iterated union
# of parametric concrete types with specific parameter values
# e.g. A{1}, A{:hello}, A{Int}
struct A{T}
end

# calls with arguments of type A may be dispatched to this method
func(a::A) = #code

# this is not valid Julia code, throws syntax error on attempt
func(a<:A) = #code

# arguments of type A, but the method is parameterized by T.
# T is available as a variable in the method body and shared with
# the parameter of an argument type a::A{T}.
# The function call must provide a known T value to dispatch to this.
# Parameters are the go-to way of using compile-time information,
# since methods are compiled on type signatures.
func(a::A{T}) where {T} = #code

# not valid code, same error
func(a<:A{T}) where {T} = #code

# the instance of Type{A} is A, so the only argument you can pass is A
# not any concrete subtypes with specified parameters, only A
func(a::Type{A}) = #code

# Type{<:A} is shorthand for (Type{S} where S<:A)
# So any subtype of A, including A itself, is accepted.
# This is not a parametric method because the method itself does not
# have a parameter, only an argument type.
func(a::Type{<:A}) = #code
1 Like

Well, Benny, you made it perfectly clear. Thank you. :pray:

Oh, probably worth mentioning this too, <: goes in where clauses of definitions, which is probably what you need to know to avoid those syntax errors. This is treated differently from the <: binary operator you can call in running code.

#        V this serves as where clause for struct, despite lack of where
struct A{T}
end

#         V no       V yes for method
func(a::A{T}) where {T} = # code

#            V yes for type, shorthand form
func(a::Type{<:A}) = # code

#                      V yes for type, full form
func(a::Type{S} where {S<:A}) = # code
1 Like