# How to create convenient single-parametric types with multiple fields

**URL:** <https://discourse.julialang.org/t/how-to-create-convenient-single-parametric-types-with-multiple-fields/59166>\
**Category:** New to Julia\
**Tags:** parametric-types, parametric-methods\
**Created:** [April 13, 2021, 7:41am UTC](https://discourse.julialang.org/t/how-to-create-convenient-single-parametric-types-with-multiple-fields/59166 "2021-04-13T07:41:47Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![nandoconde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nandoconde/32/19497_2.png) [@nandoconde](https://discourse.julialang.org/u/nandoconde)\
**Post date:** [April 13, 2021, 7:41am UTC](https://discourse.julialang.org/t/how-to-create-convenient-single-parametric-types-with-multiple-fields/59166/1 "2021-04-13T07:41:47Z")

</div>

Hello everyone!

# MWE

I have a parametric type as follows:

```julia
struct Foster_Π{T <: Number}
    zero_zero::Bool
    H::T
    ω_z::Vector{T}
    ω_p::Vector{T}
end

```

I tried at first having a non-parametric type with everything as Float64, but I could not use autodiff with it. However, now that it is parametric, it is not “smart enough” to convert constructor arguments to the same type.

For example, this errors:

```julia
H = 1
ω_z1 = Float64[4.5e9,7e9]
ω_p1 = Float64[3e9,6e9]
F_Π = Foster_Π(zero_zero, H, ω_z1, ω_p1)

```

this does not:

```julia
H = 1.0
ω_z1 = Float64[4.5e9,7e9]
ω_p1 = Float64[3e9,6e9]
F_Π = Foster_Π(zero_zero, H, ω_z1, ω_p1)

```

# Question

Is there any idiomatic way to automatically understand that the first case is just the second with an argument that casts into the rest?

I guess that using multiple dispatch, there could be Int methods that are automatically converted to the Float64 case, but having one of such methods for each field is not so funny ☹

Thanks for the help!

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [April 13, 2021, 9:04am UTC](https://discourse.julialang.org/t/how-to-create-convenient-single-parametric-types-with-multiple-fields/59166/2 "2021-04-13T09:04:00Z")

</div>

It works if you explicitly specify the type parameter,

```julia
Foster_Π{Float64}(zero_zero, H, ω_z1, ω_p1)

```

You can even force everything to other argument types, if the necessary `convert` functions exist, e.g.

```julia
Foster_Π{BigFloat}(zero_zero, H, ω_z1, ω_p1)

```

It probably wouldn’t be impossible for Julia to automatically create a constructor that coerces everything to a common type, but my guess for the motivation why this doesn’t exist is that as you say it might be quite complex, in additional to difficult to make type stable, and potentially not even be uniquely decidable, so its left to the user to specify explicitly.

---

<div class="post-metadata">

**Author:** ![nandoconde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nandoconde/32/19497_2.png) [@nandoconde](https://discourse.julialang.org/u/nandoconde)\
**Post date:** [April 13, 2021, 9:05am UTC](https://discourse.julialang.org/t/how-to-create-convenient-single-parametric-types-with-multiple-fields/59166/3 "2021-04-13T09:05:12Z")

</div>

Yay, thanks!

I hadn’t even thought about explicitly naming the type 😄

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 13, 2021, 12:02pm UTC](https://discourse.julialang.org/t/how-to-create-convenient-single-parametric-types-with-multiple-fields/59166/4 "2021-04-13T12:02:42Z")

</div>

You could also use an inner constructor that converts the fields for which coversion makes sense to type of the elements of the vectors:

```julia
julia> struct Foster_Π{T <: Number}
           zero_zero::Bool
           H::T
           ω_z::Vector{T}
           ω_p::Vector{T}
           Foster_Π(zero_zero,H,ω_z::Vector{T},ω_p::Vector{T}) where T = new{T}(zero_zero,T(H),ω_z,ω_p)
       end

julia> F_Π = Foster_Π(true, 1, [1.,2], [3.,4.])
Foster_Π{Float64}(true, 1.0, [1.0, 2.0], [3.0, 4.0])

```

(not that this will not convert the types of the vectors, but I guess that is fine, otherwise one would need to copy the data, which probably should be done explicitly if one wants to)
