# Constructor of parametric types

**URL:** <https://discourse.julialang.org/t/constructor-of-parametric-types/58136>\
**Category:** General Usage\
**Created:** [March 28, 2021, 9:07pm UTC](https://discourse.julialang.org/t/constructor-of-parametric-types/58136 "2021-03-28T21:07:00Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [March 28, 2021, 9:07pm UTC](https://discourse.julialang.org/t/constructor-of-parametric-types/58136/1 "2021-03-28T21:07:00Z")

</div>

I have the following two types. The second one is based on the first one.

```julia
struct RankOneMatrix{T} <: AbstractMatrix{T}
    v::AbstractVector{T}
    w::AbstractVector{T}
end

function Base.size(A::RankOneMatrix)
    return length(A.v), length(A.w)
end

struct RankTwoMatrix{T} <: AbstractMatrix{T}
    A::RankOneMatrix{T}
    B::RankOneMatrix{T}
    function RankTwoMatrix{T}(A::RankOneMatrix{T}, B::RankOneMatrix{T}) where T
        if size(A) != size(B)
            error("They have different dimensions.")
        end
        new(A, B)
    end
end

```

In the second type, I want the constructor to check the sizes of the two matrices are the same.  
When I call ` RankTwoMatrix(RankOneMatrix(rand(3), rand(3)), RankOneMatrix(rand(3), rand(3)))`, I got the following error.

```julia
ERROR: LoadError: MethodError: no method matching RankTwoMatrix(::RankOneMatrix{Float64},::RankOneMatrix{Float64})

```

I think I do have the matching method.  
I’ve read the manual but still have no idea what’s going on.  
Please forgive me if this is a basic question.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [March 28, 2021, 9:15pm UTC](https://discourse.julialang.org/t/constructor-of-parametric-types/58136/2 "2021-03-28T21:15:09Z")

</div>

First note that you can construct it when you are explicit with the type parameter:

```julia
julia> RankTwoMatrix{Float64}(RankOneMatrix(rand(3), rand(3)), RankOneMatrix(rand(3), rand(3)));

```

This is because when you define a custom inner constructor for a parameteric type, the outer (convenience) constructor is not automatically defined. You have to do that yourself:

```julia
julia> RankTwoMatrix(A::RankOneMatrix{T}, B::RankOneMatrix{T}) where T = RankTwoMatrix{T}(A::RankOneMatrix{T}, B::RankOneMatrix{T}) 
RankTwoMatrix

julia> RankTwoMatrix(RankOneMatrix(rand(3), rand(3)), RankOneMatrix(rand(3), rand(3)));

```

(note the `;` are necessary as the displaying does not work with you minimal example (which is ok)).

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [March 28, 2021, 9:23pm UTC](https://discourse.julialang.org/t/constructor-of-parametric-types/58136/3 "2021-03-28T21:23:42Z")

</div>

as @mauro3 noted above

You probably intended this:

```julia
struct rankTwoMatrix{T} <: AbstractMatrix{T}
           A::RankOneMatrix{T}
           B::RankOneMatrix{T}
           function rankTwoMatrix(A::RankOneMatrix{T}, B::RankOneMatrix{T}) where T
               if size(A) != size(B)
                   error("They have different dimensions.")
               end
               new{T}(A, B)
           end
       end

```

defined that way, your RankOneMatrix and RankTwoMatrix will initialize – but do not try to display them `ranktwo = RankTwoMatrix(RankOneMatrix(rand(3,3)), RankOneMatrix(rand(3,3)));`

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [March 28, 2021, 9:25pm UTC](https://discourse.julialang.org/t/constructor-of-parametric-types/58136/4 "2021-03-28T21:25:06Z")

</div>

> [@mauro3](#):
>
> This is because when you define a custom inner constructor for a parameteric type, the outer (convenience) constructor is not automatically defined. You have to do that yourself:

Great, that’s the reason. Thank you.  
Is there a better way that I can add the check to the constructor?  
The manual outer constructor

```julia
RankTwoMatrix(A::RankOneMatrix{T}, B::RankOneMatrix{T}) where T = RankTwoMatrix{T}(A::RankOneMatrix{T}, B::RankOneMatrix{T})

```

seems redundant to me.  
More precisely, is it possible to define a outer constructor to check the sizes in this example?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [March 28, 2021, 9:27pm UTC](https://discourse.julialang.org/t/constructor-of-parametric-types/58136/5 "2021-03-28T21:27:39Z")

</div>

> [@linwaytin](#):
>
> More precisely, is it possible to define a outer constructor to check the sizes in this example?

See Jeffrey’s answer.

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [March 28, 2021, 9:28pm UTC](https://discourse.julialang.org/t/constructor-of-parametric-types/58136/6 "2021-03-28T21:28:59Z")

</div>

@JeffreySarnoff Wow, thanks, I think that’s what I want.  
So in the definition `foo{T}`, the `{T}` is part of the name?  
I guess this is why I didn’t get the matched method.

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [March 28, 2021, 9:31pm UTC](https://discourse.julialang.org/t/constructor-of-parametric-types/58136/7 "2021-03-28T21:31:03Z")

</div>

Thank you both. I learned a lot.
