# Computed type annotations for struct fields

**URL:** <https://discourse.julialang.org/t/computed-type-annotations-for-struct-fields/95692>\
**Category:** General Usage\
**Tags:** parametric-types\
**Created:** [March 7, 2023, 8:42pm UTC](https://discourse.julialang.org/t/computed-type-annotations-for-struct-fields/95692 "2023-03-07T20:42:38Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![habemus-papadum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/habemus-papadum/32/4086_2.png) [@habemus-papadum](https://discourse.julialang.org/u/habemus-papadum)\
**Post date:** [March 7, 2023, 8:42pm UTC](https://discourse.julialang.org/t/computed-type-annotations-for-struct-fields/95692/1 "2023-03-07T20:42:38Z")

</div>

Is there a way to make this work in Julia:

```julia
##
function relative(t::Type{Int64})
    Float64
end

function relative(t::Type{Int32})
    Float32
end

struct Foo{T}
  a::relative(T)
  b::T
end

x = Foo{Int64}(2.0, 1)

```

This is a common and useful pattern in c++.

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [March 7, 2023, 9:25pm UTC](https://discourse.julialang.org/t/computed-type-annotations-for-struct-fields/95692/2 "2023-03-07T21:25:04Z")

</div>

What about:

```julia
relative(::Int64) = Float64
relative(::Int32) = Float32
struct Foo{T1,T2}
    a::T1
    b::T2
end
Foo(a, b::T) where T = Foo{relative(b), T}(a, b)

x = Foo(2.0, 1)
y = Foo(2.0, Int32(1))

```

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [March 7, 2023, 9:43pm UTC](https://discourse.julialang.org/t/computed-type-annotations-for-struct-fields/95692/3 "2023-03-07T21:43:02Z")

</div>

Computed field types have been an issue for several years. It’s on the 2.0 milestone list.

> <https://github.com/JuliaLang/julia/issues/18466>
>
> Currently, we can perform a limited set of logic in the type definition, such as…:
> 
> \`\`\` julia
> type A
> a::eltype(Vector{Int})
> end
> \`\`\`
> 
> but we can't involve a type parameter, such as:
> 
> \`\`\` julia
> type B{V \<: AbstractVector}
> a::eltype(V)
> end
> \`\`\`
> 
> AFAICT, at the moment the field types \`A.types\` is calculated when the type is defined and type parameters are inserted into the correct slots as they become known. 
> 
> However, it would be nice if the types could be calculated by arbitrary inferrable or \`@pure\` functions. Another simple example (close to my heart) would be:
> 
> \`\`\` julia
> immutable StaticMatrix{M,N,T}
> data::NTuple{M\*N, T}
> end
> \`\`\`
> 
> However this results in an error that multiplication is not defined for \`TypeVar\`s. Instead, I need all of this code:
> 
> \`\`\` julia
> immutable StaticMatrix{M,N,T,L}
> data::NTuple{L, T}
> function StaticMatrix(d)
> check\_params(Val{L}, Val{M}, Val{N})
> new(d)
> end
> end
> 
> @generated function check\_params{L,M,N}(::Type{Val{L}}, ::Type{Val{M}}, ::Type{Val{N}}) # could also be \`@pure\` in v0.5
> if L != M\*N
> error("Type parameters don't match")
> end
> end
> \`\`\`
> 
> and my users need to foist around the redundant \`L\` paramater when they need to specify a concrete type.
> 
> For abstract types, I'm hoping that inference itself could still be used to come up with a least-pessimistic approximation of each field, or otherwise just use \`Any\` when that's not possible. If that makes it difficult to avoid regressions, straight types (combinations of types and the relevant \`TypeVar\`s with \`apply\_type\` but no other functions) could keep functioning as they currently do.

---

<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:** [March 7, 2023, 10:36pm UTC](https://discourse.julialang.org/t/computed-type-annotations-for-struct-fields/95692/4 "2023-03-07T22:36:04Z")

</div>

> [@jbrea](#):
>
> ```julia
> struct Foo{T1,T2}
> a::T1
> b::T2
> end
> Foo(a, b::T) where T = Foo{relative(b), T}(a, b)
> 
> ```

If you want this to be a guarantee rather than just a convenience thing you can also make it an inner constructor so its impossible to construct the object in an “inconsistent” state:

```julia
struct Foo{T1,T2}
    a::T1
    b::T2
    Foo(a, b::T) where T = new{relative(b), T}(a, b)
end

```
