Manipulating Parameters of Parametrized Types

I have a struct which is composed of N components and N - 1 weights (because they add up to 1 and I don’t need the additional degree of freedom). My attempt is below

struct WeightedComponents{N}
    components::NTuple{N, Component}
    weights::NTuple{N - 1, Float64}
end

While this works for just N for both, the subtraction causes issues (probably because it doesn’t know that I’ll only use integers here. I also would be totally okay with something like this:

struct WeightedComponents
    N::Int64
    components::NTuple{N, Component}
    weights::NTuple{N - 1, Float64}
end

but that triggers an UndefVarError for N.

How should I go about making this type?

my suggestion would be make the struct:

struct WeightedComponents{N, M}
    components::NTuple{N, Component}
    weights::NTuple{M, Float64}
end

and enforce M == N-1 and sum(weights)==1 in your inner constructor.

I would probably just make components a Vector{Component} and weights a Vector{Float64}. A tuple is not really the right container for a large homogeneous collection of values. If N is large you will tax the compiler, since it will be keeping track of N different types. Although I wonder if the compiler has optimizations for NTuple, compared to tuples with arbitrary types for each element…

I’d still be interested to know how to answer the question as stated.

the answer is you can’t

I think in order to encode that kind of thing in the type system you need dependent types, which very few languages have.

Looks like this package can do it.

https://github.com/vtjnash/ComputedFieldTypes.jl