How can I constraint the parametric type within Val by an abstract type?
Consider the following function
using Unitful: Frequency, Hz
function foo(q::Val{Q}) where Q <: Frequency
return q
end
I’d like to Q to be of type Frequency.
Unfortunately, the above code errors with:
julia> foo(Val(1.0Hz))
ERROR: MethodError: no method matching foo(::Val{1.0 Hz})
The function `foo` exists, but no method is defined for this combination of argument types.
Closest candidates are:
foo(::Val{Q}) where Q<:(Union{Quantity{T, 𝐓^-1, U}, Level{L, S, Quantity{T, 𝐓^-1, U}} where {L, S}} where {T, U})
Context: I need to use Val in order to unroll a loop.
Well, yes, that’s what Val is for. But you can’t dispatch on values and their types at the same time.
The suggested syntax doesn’t make sense here. The operator <: is for subtype relationships. Int32 <: Integer makes sense, but 32 <: Integer does not. It would have to be something like
foo(::Val{Q}) where Q isa Frequency
(you normally don’t include the q in this case, since Q is the actual value.
To be clear, this isn’t valid Julia right now. I think it could be done because isa is a Core function, but I’m not certain. For now, multiple methods that constrain the Val parameter’s type can done by forwarding to a function call on the unwrapped value:
julia> begin
foo(::Val{q}) where q = _foo(q)
_foo(q::Integer) = 0
_foo(q::AbstractFloat) = 0.0
end;
julia> foo(Val(1)), foo(Val(1.0))
(0, 0.0)