Thanks for the reply, but I still have some doubt. Let’s forget the underlying meaning of `root`

and just consider it as a function. I’ll explain it in two points.

###
The reason of this convoluted definition

You have already defined some methods like

```
root(x::Float64, n::Val{:cat})
root(x::Float64, n::Val{:dog})
root(x::Float64, n::Val{true})
root(x::Float64, n::Val{false})
```

and you have code depending on that — `root(2.0, Val(a))`

with finite possibilities of `a`

.

Now you want to extend the function to Integer without refactoring the current code, it seems that the only way to go is to define

```
root(x::Float64, ::Val{n}) where n
```

This works, except that you can **no** longer extend it to float point values. That’s why I suggested the following language features:

```
root( x::Float64, ::Val{n} ) where {n::Integer}
root( x::Float64, ::Val{n} ) where {n::AbstractFloat}
```

I admit that your design may be more elegant, but it needs to refactor the code, whereas my approach provides a quick fix.

###
Infinite possibilities but with finite dispatch paths

`root(x::Float64, ::Val{n}) where n`

can handle infinite possibilities, but it does not necessarily generate infinite actual dispatch paths. If each client has several (but different) values of `n`

, it won’t be too different from functions with finite dispatch paths.

Let’s say, you write this function for many potential clients. Client A has use cases n \in \{1, 0, -1, \text{:cat} \}, Client B has use cases n \in \{2, 0, -3, \text{:dog} \}… And you cannot foresee all these use cases.

Your solution obviously still works, but I don’t see any problems of my approach in this scenario.

Edit: longer → no longer