Can `where` constrain type parameters that are instances, like `where {T isa Symbol}`

where clauses can constrain type parameters that are types e.g. where T <: Number, but I’m interested in constraining instances e.g. where T isa Symbol vs. where T isa Integer, which is not valid syntax. Is there a way to do that? I know I can work around it, but I wonder if there’s a clean way to use the typical multimethod dispatch.

what do you want to do with this?

No use case in mind, but dispatching to different methods depending on different constraints:

f(x::Val{S}) where S isa Symbol = Symbol(S, :v2)
f(x::Val{N}) where N isa Integer = N + 1

you’re taking detours for no reason:

julia> f(x::Symbol) = Symbol(x, :v2)
f (generic function with 2 methods)

julia> f(:bb)
:bbv2

julia> f(N::Integer) = N + 1
f (generic function with 3 methods)

julia> f(2)
3

in general, Julia does not like dispatch-by-value, nor does it support computed types, see GitHub - vtjnash/ComputedFieldTypes.jl: Build types in Julia where some fields have computed types FYI

2 Likes

Well, yes, but as I said, I didn’t have a use case in mind. The right-hand expressions were unimportant, that was just a minimal example of the where clauses I have in mind. I also am not interested in arbitrarily computing types in annotations or where clauses (I think I can use methods to accomplish similar things). isa just seems like a natural complement to <: for constraining type parameters, which can be either instances or types. Without it, the workaround for that example is:

f2(x::Val{T}) where T = f(T)
f(S::Symbol) = Symbol(S, :v2)
f(N::Integer) = N + 1

You are right about it not being idiomatic. Besides where-isa not being supported, I cannot think of any commonly used type parameter that is implemented as an instance of >1 type. For example, there’s no such thing as a Array{Int, :one}; N isa Int.

In general, no. where operates not on types or values directly, but TypeVars - you can think of them as a placeholder for types (and isbits values, but those don’t have computation defined in this context) and as a tool to communicate with the specialization mechanism of the compiler.

In type-speak, julia’s dispatch/parametrization/types generally does not have dependent types (save for the isbits stuff, but as you can’t compute in where with those, only in the function itself, it’s not quite there for fully dependent typing).

3 Likes

I don’t understand the type-speak stuff, but it does make sense that where isn’t working on types and values directly, so something like an isa isn’t possible. This question popped into my head because of the last two points in this comment; it was possible to jerry-rig a type-stability optimization by annotating a parametric method’s return type, but it seemed more natural to attempt to constrain the parameter based on the methods the parametric method would replace.