Something like this work for you?
type A{T, S} end
Function Execution:
f{T, S}(::Type{A{T,S}}) = T, S
Default wrappers:
f(::Type{A}) = f(A{1, 1}) f{T}(::Type{A{T}}) = f(A{T, 1}) f{S}(::Type{A{:default, S}}) = f(A{1, S})
Result:
f(A)
Since the last call is a little ugly, objects are probably the best choice if maximum flexibility is needed. In addition, designers can set restrictions on parameters, so they do not need to check the function.
Edit:
If your function has more than one argument, adding too many methods for each combination of parameters. Instead, you can define a default method for each type (only one parameter for brevity):
type A{T} end type B{T} end default{T}(::Type{A{T}}) = A{T} default(::Type{A}) = A{1} default{T}(::Type{B{T}}) = B{T} default(::Type{B}) = B{1} f{T,S}(::Type{A{T}}, ::Type{B{S}}) = T*S f{T<:A, S<:B}(a::Type{T}, b::Type{S}) = f(default(a), default(b))
At night, this has no overhead at runtime:
julia> @code_llvm f(A,B) define i64 @julia_f_62099(%jl_value_t*, %jl_value_t*)
tim
source share