How to define a new matrix type?

How do I define a thin wrapper type around a matrix?

I assumed that from LinearAlgebra should do what I want.
However, it throws an error:

struct MyMatrix{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T}
    data::S

    function MyMatrix{T,S}(data) where {T,S<:AbstractMatrix{<:T}}
        new{T,S}(data)
    end
end

A = rand(2,2)

MyMatrix(A)
ERROR: MethodError: no method matching MyMatrix(::Matrix{Float64})
Stacktrace:
 [1] top-level scope
   @ REPL[6]:1

How should it be modified to wrap any matrix into MyMatrix type?

See the array interface specification. For most functions, you probably just want to pass through to the wrapped matrix. For example, you probably want to define Base.size(x::MyMatrix) = size(x.data).

As for the error you’re seeing there, it’s because the only defined constructor requires you to specify {T,S}. You probably can just delete your inner constructor. If that doesn’t work, then define an outer constructor MyMatrix{x::S} where S<:AbstractMatrix{T} where T = MyMatrix{T,S}(x) (or something like that, I might have messed up where the wheres go).

First, if you want to use MyMatrix without parameters, you need to define a constructor that has no parameters. Then, you need to implement the interface that mikmoore pointed out. In particular, Base.size and Base.getindex. Here’s an example.

julia> begin

       struct MyMatrix{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T}
           data::S

           function MyMatrix(data::S) where {T, S<:AbstractMatrix{<:T}}
               new{T,S}(data)
           end
       end
       Base.size(m::MyMatrix) = size(m.data)
       Base.getindex(m::MyMatrix, I...) = getindex(m.data, I...)

       end

julia> M = MyMatrix(rand(2,2))
2×2 MyMatrix{Float64, Matrix{Float64}}:
 0.600174  0.638277
 0.315073  0.000486425

julia> M^2
2×2 Matrix{Float64}:
 0.561313  0.383388
 0.189252  0.201104
1 Like