Generic type parametrized by supertype

Is it possible to create a generic type whose parameter is its supertype?

I thought this would be it but it returns false.

julia> struct Foo{T} <: T where T end

julia> Foo{Int64} <: Int64
false

The problem there is that Int64 is concrete and cannot be subtyped. With Integer it should work.

The problem there is that Int64 is concrete and cannot be subtyped. With Integer it should work.

julia> Foo{Integer} <: Integer
false

That has the same result, unless I missed something.

That struct definition isn’t working the way you want it. Instead, the following three things are equivalent:

struct Foo{T} <: T where T end
struct (Foo{T} <: (T where T)) end
struct Foo{T} end

which you can confirm by running all three and not receiving any errors about struct redefinition. So you’ve actually just defined Foo{T} with no supertype, so its supertype is Any:

julia> Foo |> supertype
Any

julia> Foo{Int} |> supertype
Any

I don’t think there’s any way to do what you’re after since in Julia you can’t parameterize the supertype like that (only its type arguments, like in struct Foo{T} <: AbstractVector{T} end. If you give a little more context what you’re trying to do, someone might be able to suggest a better approach though.

1 Like

That’s helpful, thanks.

If you give a little more context what you’re trying to do, someone might be able to suggest a better approach though.

For each of several external abstract types T, I want to make a new abstract subtype of T whose dispatch I control.

For example, a const LazyInteger = Lazy{Integer} that’s a subtype of Integer but has custom lazy method implementations.

I would use

abstract type LazyInteger <: Integer end
struct LazyInt64 <: LazyInteger 
   value::Int64
end

etc.