# How to express one type related to another

**URL:** <https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416>\
**Category:** General Usage\
**Created:** [August 31, 2023, 5:53pm UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416 "2023-08-31T17:53:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ross\_Boylan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ross_boylan/32/9210_2.png) [@Ross\_Boylan](https://discourse.julialang.org/u/Ross_Boylan)\
**Post date:** [August 31, 2023, 5:53pm UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/1 "2023-08-31T17:53:40Z")

</div>

I am trying to express something like this:

```julia
struct C{T}
    foo::SomeTypeThatDependsOnT
end

```

In `C++` one could just do `T::FavoriteType` but I’m not sure what the analogue is in `julia`. I can write a function that returns a type, dependent on the argument, but I don’t think that’s going to help the compiler.

Here’s one approach that failed:

```julia
struct A
end

struct Related{T}
end

# attempt to specialize for specific types
# next is illegal: Redefinition of a constant Related
struct Related{A}
    a::Int
end

```

---

<div class="post-metadata">

**Author:** ![adamslc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adamslc/32/3452_2.png) [@adamslc](https://discourse.julialang.org/u/adamslc)\
**Post date:** [August 31, 2023, 5:58pm UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/2 "2023-08-31T17:58:47Z")

</div>

Perhaps:

```julia
julia> struct C{T, V <: Vector{T}}
           foo::V
       end

julia> C(rand(1))
C{Float64, Vector{Float64}}([0.06108395582464021])

julia> C(Number[1])
C{Number, Vector{Number}}(Number[1])

```

---

<div class="post-metadata">

**Author:** ![Ross\_Boylan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ross_boylan/32/9210_2.png) [@Ross\_Boylan](https://discourse.julialang.org/u/Ross_Boylan)\
**Post date:** [August 31, 2023, 6:03pm UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/3 "2023-08-31T18:03:58Z")

</div>

That’s a neat trick. Unfortunately, the relation between the type and the related type is more idiosyncratic in my case.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [August 31, 2023, 6:06pm UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/4 "2023-08-31T18:06:04Z")

</div>

You’ll ultimately need to use something like the the suggestion above, with “redundant” type parameters. You can use constructors (especially inner constructors) to perform the proper calculations and ensure valid combinations.

See recent discussion on [Simple compile-time evaluation for struct types](https://discourse.julialang.org/t/simple-compile-time-evaluation-for-struct-types/103326/1).

Here’s an example

```julia
struct C{T, S}
    foo::S

    function C(foo::T) where T
        S = promote_type(Float32, T) # calculation to determine S
        S <: Real || error("computed unusable type parameter S=$S") # validate S
        return new{T, S}(convert(S, foo))
    end
end

```

---

<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:** [August 31, 2023, 9:54pm UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/5 "2023-08-31T21:54:57Z")

</div>

> [@Ross\_Boylan](#):
>
> In `C++` one could just do `T::FavoriteType` but I’m not sure what the analogue is in `julia`.

Could you provide the C++ code that does what you want? I’m not familiar with C++ so I need the extra help, I can’t even immediately look up parametric structs in C++. I can’t figure out what you’re going for from the failed Julia example, it looks backwards because usually the `T` is inferred from the call `C(foo_value)`, so it’s more like `struct C{SomeTypeThatDependsOnT, T} foo::T end`. I can tell you now though that both variable types need to be put in the parameters list.

---

<div class="post-metadata">

**Author:** ![Ross\_Boylan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ross_boylan/32/9210_2.png) [@Ross\_Boylan](https://discourse.julialang.org/u/Ross_Boylan)\
**Post date:** [September 5, 2023, 10:18pm UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/6 "2023-09-05T22:18:01Z")

</div>

Since you don’t know `C++` and I’m a little rusty on it, I’m not sure it will help, but here goes:

```cpp
// C++, not julia
class A {
public:
    typedef SomeWeirdClass MyResult; //MyResult becomes and alias for previous type
};

class B {
public:
    // defines a type MyResult equal to the structure
    // doesn't create an instance of MyResult;
    struct MyResult {
       float result;
       float error;
    };
};

```

With this in place, `A::MyResult` is type `SomeWeirdClass` while `B::MyResult` is the type given in the `struct` definition.

Although this suggests that the related type is the return value of a class method, that will not necessarily be the case in my anticipated use.

---

<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:** [September 5, 2023, 10:36pm UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/7 "2023-09-05T22:36:29Z")

</div>

Yeah that sounds completely different from the first post. I don’t claim to really understand what’s going on, but that _looks_ like classes A and B form namespaces, and the `typedef` is doing a type alias. Types don’t make namespaces in Julia, and we can’t nest type definitions in each other, either. If you don’t need `A` and `B` to be types, it looks like this:

```julia
abstract type SomeWeirdClass end # assume in Main global scope

module A
  import ..Main: SomeWeirdClass # ..Main refers to Main.Main
  const MyResult = SomeWeirdClass # constant assignment serves as type alias
end

module B
  struct MyResult
    result::Float32
    error::Float32
  end
end

# aliases don't copy, they refer to the original and print as such
A.MyResult, B.MyResult # (SomeWeirdClass, Main.B.MyResult)

```

---

<div class="post-metadata">

**Author:** ![Ross\_Boylan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ross_boylan/32/9210_2.png) [@Ross\_Boylan](https://discourse.julialang.org/u/Ross_Boylan)\
**Post date:** [September 7, 2023, 12:12am UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/8 "2023-09-07T00:12:48Z")

</div>

> [@Benny](#):
>
> that _looks_ like classes A and B form namespaces, and the `typedef` is doing a type alias

Correct on both points.

As for modules, my reading of the docs is that modules can’t be used as parameters for a template, at least not unless using `Val{MyModule}`, so I’m not sure if using modules would help much. I can do

```julia
module MyA
    struct Related
        f::Float64
    end
end

module MyB
    struct Related
        i::Int32
    end
end

foo(x::MyB.Related) = println("Related structure in B has i = ", x.i)
foo(x::MyA.Related) = println("Related in A has f = ", x.f)

function go(m)
    x = m.Related(3) # type unstable
    foo(x)
end

go(MyB) # Related structure in B has i = 3

```

So I can pass around the module as a variable and use it to access the type. But I doubt the compiler is going to be able to work out the types, and so I suspect performance would not be great.

Getting back to my first post, what I had in mind was that one could do with structures what one can with functions. In `julia` one can define `f(x::A)` so that it is completely different from `f(x::B)`. So my thought was that the `struct` for `struct Related{A}` could be completely different from the definition for `struct Related{B}`. It’s not a perfect parallel since functions use the class of an instance while my fictional `struct` syntax uses the class directly.

In julia today template parameters are just placeholder names, not concrete types, and, apparently, a given structure name like `Related` can only be defined once. So there’s no specialization of structures.

The idea was partly inspired by template specialization in `C++`, which I recall does allow one to generate different code for specific classes.

---

<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:** [September 7, 2023, 12:58am UTC](https://discourse.julialang.org/t/how-to-express-one-type-related-to-another/103416/9 "2023-09-07T00:58:49Z")

</div>

> [@Ross\_Boylan](#):
>
> But I doubt the compiler is going to be able to work out the types, and so I suspect performance would not be great.

I don’t know what you mean, the `::MyB.Related` annotations? I think that’s fine, module names are `const`ants (but the kind that can be reassigned to cause obsolete inlined references, so be careful not to do that).

> [@Ross\_Boylan](#):
>
> the `struct` for `struct Related{A}` could be completely different from the definition for `struct Related{B}`

Separate parametric type definitions with the same name _are_ impossible in the same namespace. You need separate modules and distinguish the types with `ModA.Related` vs `ModB.Related`.

> [@Ross\_Boylan](#):
>
> The idea was partly inspired by template specialization in `C++`, which I recall does allow one to generate different code for specific classes.

When I asked for an example, I was thinking of this but I really couldn’t find anything that did something similar to what you seemed to be saying, and you didn’t end up providing a C++ MWE.

> [@Ross\_Boylan](#):
>
> In julia today template parameters

Don’t call these templates, that is not a thing in Julia. My intuition is that C++ templates really do just work differently from Julia’s parametric types. I assume that `Related` templated by `A` would contain `A::MyResult`, and the type `A` would internally define a type `MyResult`. In Julia, a method can associate two types `getResult(::Type{A}) = MyResult`, but like you said, a parameter `T` in a `struct Related{T}` definition is a placeholder, and crucially, `getResult(T)` evaluates during definition (and fails) instead of during instantiation where `A` can be provided. You can handle this in a constructor method because that runs during instantiation, but in the definition itself, you still need 2 parameters in the header `Related{T, DependsOnT}`.  
The reason for this limitation is Julia’s interactivity. In C++, code is set in stone by the time it reaches the compiler. In Julia, `getResult` can be redefined whenever, so it’d be disastrously ambiguous if you could instantiate and compile methods for a `MyResult`-based `Related{A}`, redefine `getResult(::Type{A}) = YourResult`, then instantiate and compile methods for a `YourResult`-based `Related{A}`. Only way to remove that ambiguity is to have another parameter `Related{A, MyResult}` vs `Related{A, YourResult}`.
