# Defining inner constructor with parametric types in Julia

Shuvomoy Das Gupta

January 12, 2021

Suppose we define the following parametric type in Julia.

``````abstract type CombinatorialProblem end

struct BinIntOptSF{V <: AbstractVector{<: Real}, M <: AbstractMatrix{<: Real}} <: CombinatorialProblem # means the concrete type BinIntOptSF is a subtype of the abstract type CombinatorialProblem
c::V
A::M
b::V
end``````

This is a parametric type. We can create an instance of this type as follows.

``````m = 4
n = 5
c = randn(n)
A = randn(m,n)
b = randn(m)
sf_bin_int_opt = BinIntOptSF(c, A, b)``````

Now suppose, we want to enforce the following check in an instance of the type: `A` must have number of rows less than or equal to number of columns, number of rows of `A` is equal number of entries in `b`, and number of columns of `A` is equal to the number of entries in `c`.

In this case we can enforce the check by writing the following inner constructor for the parametric type.

``````struct BinIntOptSF2{V <: AbstractVector{<: Real}, M <: AbstractMatrix{<: Real}} <: CombinatorialProblem

c::V
A::M
b::V

# Inner constructor
# -----------------
function BinIntOptSF2{V,M}(c::V, A::M, b::V) where {V <: AbstractVector{<: Real}, M <: AbstractMatrix{<: Real}}

if size(A,1) != size(b,1)
error("A and b have incompatible direction")
end

if size(A,1) > size(A,2)
error("A must have number of row less than or equal to number of columns")
end

if size(A,2) != size(c,1)
error("A and c have incompatible dimension")
end

new{V, M}(c,A,b)
end

# Writing the inner constructor above is going to replace the default constructor that is automatically defined by Julia. This may cause slight inconvenience, as we have to instantiate by running: bin_opt_instance = BinIntOptSF2{.,.}(...). Fortunately we can avoid this by adding the following line.

# Ensuring the one shot instantiation
# -----------------------------------
BinIntOptSF2(c::V, A::M, b::V) where {V <: AbstractVector{<: Real}, M <: AbstractMatrix{<: Real}} = BinIntOptSF2{V,M}(c,A,b)

# We need to add this line so that we can instantiate by the convenient: bin_opt_instance = BinIntOptSF2(.). If we do not add this line, but call BinIntOptSF2(.), then we will get an error "No method matching...".

end``````

Let us instantiate the type above.

``sf_bin_int_opt_2 = BinIntOptSF2(c, A, b)``