I’m don’t know how to get the compiler to recognise a type K{T} where K could be any type. For example:
abstract type AbstractGeneric{T} end
#... after defining further types <: AbstractGeneric{T} for example ... #
struct MyType{T} <: AbstractGeneric{T}
x::T
end
function myMethod(x::MyType{T}) where {T}
return 2*x.x
end
# Baby example
function fun(x::K{T}, z::AbstractArray{T}) where {K <: AbstractGeneric, T <: AbstractFloat}
return sum((myMethod(x) .- z)^2)
end
I specifically want to constrain K{T} with AbstractArray{T} on T. The compiler gives me the error:
ERROR: TypeError: in Type{...} expression, expected UnionAll, got TypeVar
I know that it will compile with:
function fun(x::AbstractGeneric{T}, z::AbstractArray{T}) where {T <: AbstractFloat}
return sum((myMethod(x) .- z)^2)
end
But that’s runtime dispatch on myMethod() which I don’t want.
This is a type of dispatch which is not allowed in Julia. The correct way to do it is indeed exactly the second thing you mention, but I didn’t understand this part:
Do you mean that in this case its its not inferred, so dispatch will happen at runtime? That’s not what I’m seeing. After a small fix to your fun by changing ^ to a .^, it looks everything is inferred hence dispatch is happening at compile time:
julia> function fun(x::AbstractGeneric{T}, z::AbstractArray{T}) where {T <: AbstractFloat}
return sum((myMethod(x) .- z).^2)
end
fun (generic function with 1 method)
julia> @code_warntype fun(MyType(1.), [1.,2,3])
Variables
#self#::Core.Compiler.Const(fun, false)
x::MyType{Float64}
z::Array{Float64,1}
Body::Float64
1 ─ %1 = Main.myMethod(x)::Float64
...
Yes, that’s what I meant. I should remember to use @code_warntype. When I think about it it makes sense or else AbstractArray would be dispatching things at run time which would be slow. It’s just that at a glance it looks like runtime polymorphism in any other language. What would be the runtime dispatch equivalent if it exists?
abstract type AbstractGeneric end
struct MyType <: AbstractGeneric
x
end
struct MySecondType <: AbstractGeneric
x
y
end
function myMethod(x::MyType)
return 2*x.x
end
function fun(x::AbstractGeneric, z::AbstractArray)
return sum((myMethod(x) .- z).^2)
end
@code_warntype fun(MyType(3), rand(5))