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.

2 Likes

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…

3 Likes

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.

2 Likes

Looks like this package can do it.

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

1 Like