# Inner constructor, correct type for \`new\`

**URL:** <https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013>\
**Category:** General Usage\
**Created:** [January 31, 2020, 9:09am UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013 "2020-01-31T09:09:28Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![timueh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timueh/32/12379_2.png) [@timueh](https://discourse.julialang.org/u/timueh)\
**Post date:** [January 31, 2020, 9:09am UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/1 "2020-01-31T09:09:28Z")

</div>

I have a question about what to write in the curly braces of the `new{...}()` function for inner constructors.

Consider this piece of code

```julia
struct MyType{T} <: MyAbstractType{T}
    x::T
    y::T
    function MyType(x, y)
        correct_type = typeof(x) # not correct
        new{correct_type}(x,y)
    end
end

```

Then, this works

```julia
julia> MyType(rand(4), rand(4))
MyType{Array{Float64,1}}([0.9150136845996055, 0.4716452018442112, 0.5171312730495929, 0.17248549404109959], [0.11250545680318513, 0.13957724361626078, 0.7669385479426463, 0.6556434276837464])

```

but—not surprisingly—automatic promotion won’t

```julia
julia> MyType([1,2,3,4], rand(4))
ERROR: InexactError: Int64(0.6071962222148559)

```

**My question:** What’s the correct way to pick the _larger_ of the two types of `x` and `y` in the function argument?

---

<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:** [January 31, 2020, 9:30am UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/2 "2020-01-31T09:30:36Z")

</div>

```julia
struct MyType{T}
    x::T
    y::T
end

```

This says that the type of `x` and the type of `y` are the same specific type.  
`myitem = MyType(1, 2)` and `myvecs = MyType([1,2], [3,4,5])` do the right thing, no explicit constructor needed. What are you trying to achieve?

Your example `MyType([1,2,3,4], rand(4))` is like `MyType([1,2], [1.0, 2.0])` asks for two different types (`Vector{Int}` and `Vector{Float64}`) to be interpreted as the same type.

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [January 31, 2020, 9:35am UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/3 "2020-01-31T09:35:45Z")

</div>

you can use `promote_type`:

```julia
abstract type MyAbstractType{T} end

struct MyType{T} <: MyAbstractType{T}
    x::T
    y::T
    MyType(x, y) = new{promote_type(typeof(x),typeof(y))}(x,y)
end

julia> MyType([1,2,3,4], rand(4))
MyType{Array{Float64,1}}([1.0, 2.0, 3.0, 4.0], [0.8299166987571895, 0.1703207971478411, 0.3693947055390745, 0.054196777407508945])

```

---

<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:** [January 31, 2020, 9:38am UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/4 "2020-01-31T09:38:30Z")

</div>

You can do something like this:

```julia
abstract type MyAbstractType{T} end

struct MyType{T} <: MyAbstractType{T} 
  x::T
  y::T
end

function MyType(x::T1, y::T2) where {T1, T2}
     xx, yy = promote(x, y)
     return MyType(xx, yy)
end

```

then

```julia
julia> MyType([1,2], [3.0,4.0,5.0])
MyType{Array{Float64,1}}([1.0, 2.0], [3.0, 4.0, 5.0])

```

assuming you are storing vectors, this is better (more explicit, tighter filter).

```julia
julia> abstract type MyAbstractElementType{T} end

julia> struct MyType{T} <: MyAbstractElementType{T}
         x::Vector{T}
         y::Vector{T}
       end

julia> function MyType(x::Vector{T1}, y::Vector{T2}) where {T1, T2}
            xx, yy = promote(x, y)
            return MyType(xx, yy)
       end

```

---

<div class="post-metadata">

**Author:** ![timueh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timueh/32/12379_2.png) [@timueh](https://discourse.julialang.org/u/timueh)\
**Post date:** [January 31, 2020, 11:11am UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/5 "2020-01-31T11:11:06Z")

</div>

Thanks for the helpful response; `promote_type` is the answer.

I just realized that there is one assumption I didn’t share: the fields `x` and `y` should have the same length. Hence, the inner constructor in which I can check for that.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 31, 2020, 12:08pm UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/6 "2020-01-31T12:08:13Z")

</div>

> [@timueh](#):
>
> What’s the correct way to pick the _larger_ of the two types of `x` and `y` in the function argument?

This is not a well-defined question: there is no total ordering in types. Eg when `x::Int` and `y::String`, neither is `<:` of the other. I am assuming you are looking for a type both can be converted to.

It is customary to define an inner constructor only if you want to check or calculate something. Otherwise, you would define an outer constructor with promotion,

```julia
struct MyType{T}
    x::T
    y::T
end

MyType(x, y) = MyType(promote(x, y))

```

This is actually done by default if you don’t define an inner constructor.

See [Constructors · The Julia Language](https://docs.julialang.org/en/v1/manual/constructors/#Parametric-Constructors-1) and the references there.

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [January 31, 2020, 12:38pm UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/7 "2020-01-31T12:38:39Z")

</div>

> [@Tamas\_Papp](#):
>
> This is actually done by default if you don’t define an inner constructor.

In your example:

```julia
struct MyType{T}
    x::T
    y::T
end

julia> MyType(promote(1, 1.0))
ERROR: MethodError: no method matching MyType(::Tuple{Float64,Float64})
....

```

???

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 31, 2020, 12:39pm UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/8 "2020-01-31T12:39:51Z")

</div>

Forgot splicing, it is

```julia
MyType(x, y) = MyType(promote(x, y)...)

```

Please do read the manual, it is described in detail.

---

<div class="post-metadata">

**Author:** ![timueh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timueh/32/12379_2.png) [@timueh](https://discourse.julialang.org/u/timueh)\
**Post date:** [January 31, 2020, 2:41pm UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/9 "2020-01-31T14:41:13Z")

</div>

> [@Tamas\_Papp](#):
>
> This is not a well-defined question: there is no total ordering in types. Eg when `x::Int` and `y::String` , neither is `<:` of the other. I am assuming you are looking for a type both can be converted to.
> 
> It is customary to define an inner constructor only if you want to check or calculate something. Otherwise, you would define an outer constructor with promotion,

I am completely with you. As mentioned, I forgot to disclose some hidden assumptions, namely that `x` and `y` are vectors of equal length with numerical entries.

---

<div class="post-metadata">

**Author:** ![timueh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timueh/32/12379_2.png) [@timueh](https://discourse.julialang.org/u/timueh)\
**Post date:** [January 31, 2020, 2:43pm UTC](https://discourse.julialang.org/t/inner-constructor-correct-type-for-new/34013/10 "2020-01-31T14:43:06Z")

</div>

> [@Tamas\_Papp](#):
>
> Please do read the manual, it is described in detail.

Also here I am completely with you. The Julia manual is extremely helpful. Sometimes it’s just that I do not know where to look for what. Once you know the right key word, off you go. But we digress. Thanks, anyway!
