How to restrict type parameter to be subclass of a parameterized type

I am looking to perform something like this:

abstract type Foo{T} end

struct Bar{T, U} <: Foo{U}
    bar :: U
end

struct Baz{T} <: Foo{U} where T <: Foo{U} where U
    baz :: U
end

That is I would like to parameterize a Baz by a Bar in a way that the baz property of the Baz has the same type as the bar property of the Bar. Both Baz and Bar should subtype the Foo that is parameterized by their field type.

I have tried a bunch of ways of trying to get the concept but they all throw an error. Namely below I show what I have tried

struct Baz{T} <: Foo{U} where T <: Foo{U} where U
    baz :: U
end

struct Baz{T} <: Foo{U} where T <: Foo{U}
    baz :: U
end

struct Baz{T where T <: Foo{U}} <: Foo{U}
    baz :: U
end

struct Baz{Foo{U}} <: Foo{U}
    baz :: U
end

What am I missing here? Is this possible?

#         This part is the struct's where clause.
#         U written first because T<:Foo{U} depends on U
#         vvvvvvvvvvvvvv
struct Baz{U, T<:Foo{U}} <: Foo{U}
  baz :: U
end

where {T<:Foo{U}} where U is equivalent to where {U, T<:Foo{U}}, it’s just you need to write it like the latter because you can’t write where, let alone chains of them, in a struct definition’s where clause. You can write where in iterated union types annotating the fields, though.

1 Like