# Parametric types & instances

**URL:** <https://discourse.julialang.org/t/parametric-types-instances/125213>\
**Category:** General Usage\
**Tags:** question, parametric-types\
**Created:** [January 26, 2025, 3:51am UTC](https://discourse.julialang.org/t/parametric-types-instances/125213 "2025-01-26T03:51:05Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)\
**Post date:** [January 26, 2025, 3:51am UTC](https://discourse.julialang.org/t/parametric-types-instances/125213/1 "2025-01-26T03:51:05Z")

</div>

I have ~20 trade types. Each has a rate-set struct and a rate-set-instance struct.  
I’d like to define the rate-sets and rate-set-instances jointly (botom example).  
There are ~3 rate-set field types and each has a unique rate-set-instance field type e.g.

```
rate_set rate_set_instance
Currency Float64
Interest_Rate Interpolation{curve}
Volatility Interpolation{surface}

```

```julia
struct deal_type_A_rate_set
    fx_rate::Currency
    ir_curve::Interest_Rate
end

struct deal_type_A_rate_set_instance
    fx_rate::Float64
    ir_curve::Interpolation
end

#could it be done like this
struct deal_type_A_rate_set{instance}
    FX_rate:: (instance ? Float64 : Currency )
    IR_curve::(instance ? Interpolation : InterestRate )
end

```

---

<div class="post-metadata">

**Author:** ![marteaua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marteaua/32/214927_2.png) [@marteaua](https://discourse.julialang.org/u/marteaua)\
**Post date:** [January 26, 2025, 4:52am UTC](https://discourse.julialang.org/t/parametric-types-instances/125213/2 "2025-01-26T04:52:14Z")

</div>

If the issue is only factorizing code, wouldn’t it be better to do the reverse, having a type for sets and one for set instances, and have another type representing the ~20 trades, that parametrize the sets?

```julia
abstract type Trade end

struct Trade_A <: Trade end
struct Trade_B <: Trade end
# ...

struct RateSet{T<:Trade}
    fx_rate::Currency
    ir_curve::Interest_Rate
end

struct RateSetInstance{T<:Trade} 
    fx_rate::Float64
    ir_curve::Interpolation
end

```

You can define functions that use `fx_rate` regardless of which type the Rate has but they won’t be type stable:

```julia
function get_fx_rate(rs::Union{RateSet,RateSetInstance})
    return rs.fx_rate # !!! Not type stable !!! return type is Currency or Float64
end

```

You can also define behavior for all trades or certain trades only using dispatch:

```julia
function generic_method_for_RateSet(rs::RateSet)
    # something on any RateSet
end

function compute_rate(ri::RateSetInstance{Trade_A})
    # something specific for Trade_A
end

```

If you really want the type of the field to change like you asked while keeping type concreteness, an option is to put the inner types as parameters:

```julia
struct GenericRateSet{T_FX, T_IR} 
    fx_rate::T_FX
    ir_curve::T_IR

    GenericRateSet{T_FX, T_IR}(fx_rate::T_FX, ir_curve::T_IR) 
        #you could check here that T_FX and T_IR are what you expect
        new{T_FX, T_IR}(fx_rate, ir_curve)
    end
end

```

and possibly use type aliases for dispatch/syntaxic sugar:

```julia
const RateSet = GenericRateSet{Currency,Interest_Rate}
const RateSetInstance = GenericRateSet{Float64,Interpolation}

```

But this second option in not very idiomatic, if two struct have different fields, make two different structs… Or use a generic struct with untyped field if there is no risk of performance issues.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 26, 2025, 4:55am UTC](https://discourse.julialang.org/t/parametric-types-instances/125213/3 "2025-01-26T04:55:02Z")

</div>

You’d need to derive 2 more type parameters in the constructor. While it’s hypothetically possible for core, unchangeable operations like `?:` to derive more parameters from fewer without method invalidation bugs, that’s not supported.

Do you really need to put them in one parametric type? `X{true}` and `X{false}` are disjoint subsets, could you just do a two-member `Union`?

---

<div class="post-metadata">

**Author:** ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)\
**Post date:** [January 26, 2025, 6:33am UTC](https://discourse.julialang.org/t/parametric-types-instances/125213/4 "2025-01-26T06:33:44Z")

</div>

Since I’ll have ~20 of these. I didn’t want to define each twice.

```julia
struct deal_type_A_rate_set
    fx_rate::Currency
    ir_curve::Interest_Rate
end

# 20 other deal_type_rate_set structs...

struct deal_type_Q_rate_set
   fx_rate1::Currency
   fx_rate2::Currency
   ir_curve1::Interest_Rate
   ir_curve2::Interest_Rate
   fx_vol::FX_Volatility
end

```

The proposed union and parametric approaches both achieve this:

```julia
struct deal_type_A_rate_set
    fx_rate::Union{Currency,Float64}
    ir_curve::Union{Interest_Rate,Interpolation}
end

struct deal_type_A_rate_set{Tfx,Tir}
    fx_rate::Tfx
    ir_curve::Tir
end

```

I just wanted to be more explicit about whether a version was the ‘base’ or ‘instance’ version.

A VaR calc would use a struct array of 1,000 instances, which I’d like to put on a GPU. (the union approach might make this difficult)

---

<div class="post-metadata">

**Author:** ![marteaua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marteaua/32/214927_2.png) [@marteaua](https://discourse.julialang.org/u/marteaua)\
**Post date:** [January 26, 2025, 7:34am UTC](https://discourse.julialang.org/t/parametric-types-instances/125213/5 "2025-01-26T07:34:27Z")

</div>

Be carefull that the types of the fields of

```julia
struct deal_type_A_rate_set
    fx_rate::Union{Currency,Float64}
    ir_curve::Union{Interest_Rate,Interpolation}
end

```

are [ambiguous](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-fields-with-abstract-type) (their concrete types cannot be inferred from the type of the struct), so it might not be performant, I’m not sure this corresponds to what @Benny suggested.

---

<div class="post-metadata">

**Author:** ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)\
**Post date:** [January 26, 2025, 7:41am UTC](https://discourse.julialang.org/t/parametric-types-instances/125213/6 "2025-01-26T07:41:47Z")

</div>

I’d like a parametric union

```julia
FX_parametric = {instance ? Float64 : Currency }
IR_parametric = {instance ? Interpolation : Interest_Rate}

struct deal_type_A_rate_set{instance}
    fx_rate::FX_parametric(instance)
    ir_curve::Interest_Rate(instance)
end

```

each parametric union type could be defined once then used in 20 deal\_type\_rate\_sets
