Just for laziness I would like to implement a repeat
function for my own parametric type. For example, consider the following example, where A1
might even be used recursively (i.e. Arrays of Arrays) and I would like to do a simple repeat (introducing one further dimension, here a second one)
import Base: size, repeat
abstract type A end
struct A1{C<:Array{<:A,N} where N} <: A
value::C
end
struct A2{T} <: A
value::T
end
size(a::A1) = size(a.value)
repeat(a::A1; inner=nothing, outer=nothing) = A1( repeat(a.value; inner=inner, outer=outer) )
repeat(a::A1, counts...) = A1( repeat(a.value, counts...) )
function runExample()
a = A1([ A2(0.2); A2(0.2)])
s = length(size(a))
d = fill(1,s+1)
d[s+1] = s
return repeat(a; inner=d)
end
@code_warntype runExample()
runExample()
While the example runs perfectly (last line) the @code_warntype
says that it can’t infer the type of the repeat return, i.e.
11 ─ %25 = invoke Main.:(#repeat#8)(%7::Array{Int64,1}, %10::Nothing, %9::Function, %4::A1{Array{A2{Float64},1}})::A1{_1} where _1
I started trying something like
repeat(a::A1{Ca}; inner=nothing, outer=nothing) where {Ca <: Array{C,N} where {C <: A, N}} = ...
however the new type will have a different N
, since the array dimensions change, so I don’t know how to continue. Actually the problem is similar for cat
, vcat
and hcat
.
How can I properly define repeat
to not avoid the type instability?