http://docs.julialang.org/en/stable/manual/faq/#how-should-i-declare-abstract-container-type-fields
On Monday, November 30, 2015 10:44:58 AM Mauro wrote:
> You (kinda) have to provide an outer constructor as well.
>
> julia> immutable ArrayWrapper{T,N,AT <: AbstractArray} <: AbstractArray{T,N}
> arr::AT
> function ArrayWrapper(arr)
> @assert T==eltype(arr) && length(size(arr))==N
> new(arr)
> end
> end
>
> Without outer constructor you need to specify the parameters:
>
> julia> ArrayWrapper{Float64, 2, Array{Float64,2}}(rand(3,3));
>
> If you do it wrong the assertion will error:
>
> julia> ArrayWrapper{Float64, 3, Array{Float64,2}}(rand(3,3));
> ERROR: AssertionError: T == eltype(arr) && length(size(arr)) == N
> in call at none:4
>
>
> Probably define this outer constructor:
>
> julia> ArrayWrapper{AT<:AbstractArray}(arr::AT) = ArrayWrapper{eltype(arr),
> length(size(arr)), AT}(arr) ArrayWrapper{T,N,AT<:AbstractArray{T,N}}
>
> julia> ArrayWrapper(rand(4,4));
>
> Note that I suppressed output because there is some error in the show
> method. I think you have to provide certain functions to make it work.
> See http://docs.julialang.org/en/release-0.4/manual/interfaces/
>
> On Mon, 2015-11-30 at 10:18, Andrei Zh <[email protected]> wrote:
> > Hmm, seems like this gives an error when constructing a type:
> >
> > julia> ArrayWrapper(rand(3, 4))
> > ERROR: MethodError: `convert` has no method matching convert(::Type{
> > ArrayWrapper{T,N,AT<:AbstractArray{T,N}}}, ::Array{Float64,2})
> > This may have arisen from a call to the constructor ArrayWrapper{T,N,AT<:
> > AbstractArray{T,N}}(...),
> > since type constructors fall back to convert methods.
> >
> > Closest candidates are:
> > call{T}(::Type{T}, ::Any)
> > convert{T}(::Type{T}, ::T)
> >
> > in call at essentials.jl:57
> >
> > Moving constructor outside type definition doesn't work too.
> >
> > On Monday, November 30, 2015 at 12:00:10 PM UTC+3, Mauro wrote:
> >> > I'm trying to do something like this (which doesn't compile in its
> >>
> >> current
> >>
> >> > form):
> >> >
> >> > type ArrayWrapper{T,N,AT <: AbstractArray{T,N}} <: AbstractArray{T,N}
> >> >
> >> > arr::AT{T,N}
> >> >
> >> > end
> >> >
> >> > That is:
> >> > - wrapper around any type AT inherited from AbstractArray{T,N}
> >> > - wrapper should be itself parametrized by T and N
> >> > - wrapper should itself extend AbstractArray{T,N}
> >> >
> >> > The code above currently gives an error:
> >> >
> >> > ERROR: TypeError: instantiate_type: expected TypeConstructor, got
> >>
> >> TypeVar
> >>
> >> > and the closest thing that works looks like this:
> >> > type ArrayWrapper{T,N,AT <: AbstractArray} <: AbstractArray{T,N}
> >> >
> >> > arr::AT
> >> >
> >> > end
> >> >
> >> > which looks too unconstrained.
> >> >
> >> > Is there a way to get what I need?
> >>
> >> If you're ok with using immutable (note, you can still modify the array,
> >> just not its binding), this should work:
> >>
> >> immutable ArrayWrapper{T,N,AT <: AbstractArray} <: AbstractArray{T,N}
> >>
> >> arr::AT
> >> function ArrayWrapper(arr)
> >>
> >> @assert T==eltype(arr) && length(size(arr))==N
> >> new(arr)
> >>
> >> end
> >>
> >> end