Impose two conditions on parametric type

I have a type defined as _NumericalInput = Union{Float64, Vector{Float64}}.
I’d like to implement a function like:

get(x::Float64, t::Int) = x
get(x::Vector{Float64}, t::Int) = x[t]

But as soon as I change _NumericalInput, (i.e. including Int64) I would need to remember to get back to that and change it. So what I would like to do is:

get(x::T, t::Int) where T <: _NumericalInput = x
get(x::T, t::Int) where T <: _NumericalInput AND T <: Vector = x[t]

Basically implementing get(...) for all types that are a _NumericalInput conditioned on whether they are subtype of Vector or not.

You could use a barrier like the above, or an assertion. But this is not very idiomatic, why not just make the functions generic for numbers and vectors?

You could use a barrier like the above, or an assertion.

The barrier is a nice idea, that way it at least works. I still feel though this does feel a bit unintuitive (or rather non-elegant).

But this is not very idiomatic, why not just make the functions generic for numbers and vectors?

This would allow me to call get(["a"], 1). But that should fail, since Vector{String} is not a valid _NumericalInput.


Maybe there is a way to contruct a “conditional subtype”? I know I can access all vector types for example through:

[t for t in Base.uniontypes(_NumericalInput) if t <: Vector]

Is there a way to create a subtype (at compile time) from that? Basically creating this:

_NumericalVectorInput = Union{t for t in Base.uniontypes(_NumericalInput) if t <: Vector}

and using get(x::_NumericalVectorInput, t::Int) afterwards.

Why not just AbstractVector{<: Number} ? Do you really want to restrict to not accept Float32 for instance?

Many times is advantageous to just let the signature generic and let the error appear down the line. (Most Julia code is written like that)

And if you want a more precise error message add a barrier on the very top of the user input to assert the type of variable that are supported.

Why not just AbstractVector{<: Number} ? Do you really want to restrict to not accept Float32 for instance?

It seems like this would be the best approach for my current problem. Thanks!

Do you really want to restrict to not accept Float32 for instance?

It was more meant to prevent erroneous inputs as either Float or Int when only one of them is allowed. But I can check for that elsewhere and not restrict the type, which was probably a stupid idea to begin with.

(but, on a general scope, it essentially comes down to a workaround, due to the parametric type system being strangely restricting… allowing ranges with S <: T <: U, but not multiple conditions?!)