# Writing a new type for a specific kind of array (constructor error)

**URL:** <https://discourse.julialang.org/t/writing-a-new-type-for-a-specific-kind-of-array-constructor-error/62900>\
**Category:** New to Julia\
**Created:** [June 14, 2021, 5:43pm UTC](https://discourse.julialang.org/t/writing-a-new-type-for-a-specific-kind-of-array-constructor-error/62900 "2021-06-14T17:43:30Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![gpownall](https://avatars.discourse-cdn.com/v4/letter/g/dc4da7/32.png) [@gpownall](https://discourse.julialang.org/u/gpownall)\
**Post date:** [June 14, 2021, 5:43pm UTC](https://discourse.julialang.org/t/writing-a-new-type-for-a-specific-kind-of-array-constructor-error/62900/1 "2021-06-14T17:43:30Z")

</div>

I’m trying to define a new type for array with the following conditions:

- It must be square and two-dimensional
- The elements of each column must sum to 1
- Ideally it would be a subtype of two-dimensional arrays so that I can use the already-written functions for finding the inverse matrix, eigenvalues and eigenvectors, etc.

There will eventually be functions written which are specific to this kind of array, and I have a nice use case for them, but right now I’m struggling to even get the constructor working and would really appreciate some help.

Here is the MWE:

```julia
struct ProbMatrix{T<:Real} <: AbstractArray{T,2}
        data

        function ProbMatrix{T}(data::Array{T,2}) where T<:Real
                if ndims(data) != 2
                        error("Probability matrix needs to be two-dimensional")
                end
                if size(data,1) != size(data,2)
                        error("Probability matrix needs to be square.")
                end
                for col_num in 1:size(data,1)
                        if sum(data[:,col_num]) != 1
                                error("Each column of a probability matrix must sum to one.")
                        end
                end
                new{T}(data)
        end
end

Mat = [0.8 0.05 ; 0.2 0.95]

println(inv(Mat))

A = ProbMatrix(Mat)

println(inv(A))

```

The following error is raised:

ERROR: LoadError: MethodError: no method matching ProbMatrix(::Array{Float64,2})

…which I don’t understand as I thought I had quite specifically defined this case?

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 14, 2021, 6:16pm UTC](https://discourse.julialang.org/t/writing-a-new-type-for-a-specific-kind-of-array-constructor-error/62900/2 "2021-06-14T18:16:09Z")

</div>

Welcome @gpownall !

Here you go:

```julia
struct ProbMatrix{T<:Real} <: AbstractArray{T,2}
        data
        function ProbMatrix(data::Array{T,2}) where T<:Real
                if ndims(data) != 2
                        error("Probability matrix needs to be two-dimensional")
                end
                if size(data,1) != size(data,2)
                        error("Probability matrix needs to be square.")
                end
                for col_num in 1:size(data,1)
                        if sum(data[:,col_num]) != 1
                                error("Each column of a probability matrix must sum to one.")
                        end
                end
                new{T}(data)
        end
end

Base.size(m::ProbMatrix{T}) where T = size(m.data)

Mat = [0.8 0.05 ; 0.2 0.95]

println(inv(Mat))

A = ProbMatrix(Mat);

```

As your struct is subtyped `AbstractArray{T,2}` , `size` needs to be defined for the new type.

There is more, you have to define, e.g. `getindex` . You get the error if you omit the `;` in the last line:

```julia
julia> A = ProbMatrix(Mat)
2×2 ProbMatrix{Float64}:
Error showing value of type ProbMatrix{Float64}:
ERROR: getindex not defined for ProbMatrix{Float64}

```

We had another similar thread, where you can find a few details about what was wrong in general: [Inner constructor – checking for equal lengths](https://discourse.julialang.org/t/inner-constructor-checking-for-equal-lengths/62413)

---

<div class="post-metadata">

**Author:** ![bert](https://avatars.discourse-cdn.com/v4/letter/b/9e8a1a/32.png) [@bert](https://discourse.julialang.org/u/bert)\
**Post date:** [June 14, 2021, 6:23pm UTC](https://discourse.julialang.org/t/writing-a-new-type-for-a-specific-kind-of-array-constructor-error/62900/3 "2021-06-14T18:23:37Z")

</div>

You only defined `ProbMatrix{T}(::Array{T,2})`, but you’re trying to call `ProbMatrix(::Array{T,2})`. The easiest way to solve this is to just add an outer constructor.

```nohighlight
ProbMatrix(data::Array{T,2}) where {T} = ProbMatrix{T}(data)

```

But even if you define this you’ll notice that you can’t actually print your array. That’s because you need to define a handful of other methods to adopt the [`AbstractArray` interface](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array).

Also I think you should replace `Array{T,2}` with `AbstractArray{T,2}`, but that’s a separate issue.

---

<div class="post-metadata">

**Author:** ![gpownall](https://avatars.discourse-cdn.com/v4/letter/g/dc4da7/32.png) [@gpownall](https://discourse.julialang.org/u/gpownall)\
**Post date:** [June 14, 2021, 6:25pm UTC](https://discourse.julialang.org/t/writing-a-new-type-for-a-specific-kind-of-array-constructor-error/62900/4 "2021-06-14T18:25:19Z")

</div>

Understood, thanks!
