# How to skip type parameters in function signature

**URL:** <https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300>\
**Category:** General Usage\
**Created:** [November 16, 2023, 7:05am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300 "2023-11-16T07:05:47Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [November 16, 2023, 7:05am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/1 "2023-11-16T07:05:47Z")

</div>

I have a type such as:

```julia
struct Foo{A,B}
    a::A
    b::B
end

```

And a method for `foo` where I want to use the type parameter `A`. Then I can write:

```julia
mymethod(x::Foo{A,B}) where {A,B} = ...

```

But since I don’t need `B`, I could just write:

```julia
mymethod(x::Foo{A}) where {A} = ...

```

Is there also a way of telling “I don’t need the first type parameter, but I do want the second”?

`mymethod(x::Foo{_,B}) where B` doesn’t work; it’s an “all-underscore identifier used as rvalue” syntax error.

That would be useful for more complex types with many type parameters.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [November 16, 2023, 7:27am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/2 "2023-11-16T07:27:45Z")

</div>

> [@heliosdrm](#):
>
> `mymethod(x::Foo{A}) where {A}`

You’re not skipping `B` there either, it’s a shorthand for a `where` clause: `::Foo{A,Bi} where Bi`. Julia didn’t used to [print shorthands of UnionAll types](https://discourse.julialang.org/t/printing-of-unionall-types-is-misleading-as-of-julia-version-1-7/89418), so it’s worth checking with `typeof` now.

> [@heliosdrm](#):
>
> Is there also a way of telling “I don’t need the first type parameter, but I do want the second”?

You can do something similar to omit the 1st parameter from the method’s where clause, but it must be made clear there is a type parameter there rather than some other type from the global scope: `mymethod(x::Foo{Ai, B} where Ai) where {B}`. `Ai` will not be available as a variable in the method body, it’s limited to the parametric type expression.

> [@heliosdrm](#):
>
> it’s an “all-underscore identifier used as rvalue” syntax error.

`_` is just a variable, not some placeholder token, and all-underscore variables are intended solely for throwaway assignments, so they can only show up on the left hand side of `=`. If you replaced it with a variable `Ai`, you’d hit an undefined variable error because `Ai` isn’t assigned in the outer scope or specified in a `where` clause.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [November 16, 2023, 7:41am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/3 "2023-11-16T07:41:43Z")

</div>

```julia
mymethod(x::Foo{<:Any,B}) where {B}

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [November 16, 2023, 8:30am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/4 "2023-11-16T08:30:57Z")

</div>

> [@danielwe](#):
>
> `Foo{<:Any,B}`

Worth pointing out that despite looking like the parameter must be a type, `<:Any` doesn’t actually check for subtyping, so this will also work for types (not `Foo`) with type parameters that are not types.

```julia
julia> Val{<:Any} == (Val{T} where {T<:Any}) == Val{T} where T
true

julia> 1<:Any
ERROR: TypeError: in <:, expected Type, got a value of type Int64
...
julia> Val{1} <: Val{<:Any} # 1<:Any is not checked
true

julia> Val{1} <: Val{<:Number} # 1<:Number is checked
false

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 17, 2023, 12:07am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/5 "2023-11-17T00:07:28Z")

</div>

> [@Benny](#):
>
> Worth pointing out that despite looking like the parameter must be a type, `<:Any` doesn’t actually check for subtyping

This seems more like a bug than a feature. I wouldn’t advocate relying on this behavior in your code.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [November 17, 2023, 12:57am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/6 "2023-11-17T00:57:47Z")

</div>

> [@stevengj](#):
>
> This seems more like a bug than a feature. I wouldn’t advocate relying on this behavior in your code.

Maybe, but it can’t be changed without breaking working code. Since it is here to stay in v1.x, might as well leverage it for using a `where` clause shorthand to its fullest.

Not that it matters for the thread, but my actual preference is putting only names in the parameter clause (`Vector{T} where T<:Number` instead of `Vector{<:Number}`) and avoiding nested `where` clauses (`where {S,T<:S}` instead of `where T<:S where S`) to mirror the syntax of `struct`s. I’m not above writing unused method parameters to save writing `where` clauses for individual arguments; `f(::Array{<:Any, N}) where N` is not a different method from `f(::Array{T, N}) where {T,N}` and the extra method parameter doesn’t affect compilation. OP may have a different preference and `Foo{<:Any,B}` seems as brief of an individual `where` clause without introducing ambiguity.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 17, 2023, 1:13am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/7 "2023-11-17T01:13:52Z")

</div>

> [@Benny](#):
>
> Maybe, but it can’t be changed without breaking working code.

… obligatory [xkcd link](https://xkcd.com/1172).

If it’s a bug — if it’s an undocumented behavior that violates the documented behavior of `<:` — then any code that relies on it is broken, and it can be freely changed in 1.x.

> <https://github.com/JuliaLang/julia/issues/52201>
>
> This behavior, \[pointed out on discourse\](https://discourse.julialang.org/t/how-…to-skip-type-parameters-in-function-signature/106300/4?u=stevengj), seems like a bug (violating the documented meaning of \`\<:\`):
> \`\`\`jl
> julia\> Val{\<:Any} == (Val{T} where {T\<:Any}) == Val{T} where T
> true
> 
> julia\> 1\<:Any
> ERROR: TypeError: in \<:, expected Type, got a value of type Int64
> ...
> julia\> Val{1} \<: Val{\<:Any} # 1\<:Any is not checked
> true
> 
> julia\> Val{1} \<: Val{\<:Number} # 1\<:Number is checked
> false
> \`\`\`

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [November 17, 2023, 2:48am UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/8 "2023-11-17T02:48:38Z")

</div>

I see someone linked an existing closed issue that recently still had active debate

> <https://github.com/JuliaLang/julia/issues/9580>
>
> When a type parameter is specified to be \`T \<: Top\`, it actually accept non-type… as parameters as well.
> 
> \`\`\` julia
> julia\> type A{T\<:Top}
> end
> 
> julia\> A{1}
> A{1}
> 
> julia\> A{1.2}
> A{1.2}
> \`\`\`
> 
> Although \`1\` and \`1.2\` are clearly not subtypes of \`Top\`
> 
> \`\`\` julia
> julia\> 1 \<: Top
> ERROR: type: subtype: expected Type{T\<:Top}, got Int64
> 
> julia\> 1.2 \<: Top
> ERROR: type: subtype: expected Type{T\<:Top}, got Float64
> \`\`\`
> 
> This is also the case for the builtin \`Type\` (some other types like \`Array\` doesn't even have this constraint specified)
> 
> \`\`\` julia
> julia\> Type
> Type{T\<:Top}
> 
> julia\> Type{1}
> Type{1}
> 
> julia\> Type{1.2}
> Type{1.2}
> \`\`\`
> 
> No error is raised even if this parameter is used as a type of a field
> 
> \`\`\` julia
> julia\> type A{T\<:Top}
> a::T
> end
> 
> julia\> A{1}
> A{1}
> 
> julia\> A{1}.names
> (:a,)
> 
> julia\> A{1}.types
> (1,)
> \`\`\`
> 
> The same thing happens for \`T \<: Any\` although this time it correctly reject \`Core.Unref\`
> 
> \`\`\` julia
> julia\> type A{T \<: Any}
> end
> 
> julia\> A{1}
> A{1}
> 
> julia\> A{1.2}
> A{1.2}
> 
> julia\> A{Core.Undef}
> ERROR: type: A: in T, expected T, got Type{Undef}
> 
> julia\> Core.Undef \<: Any
> false
> \`\`\`
> 
> Specifying other types seems fine
> 
> \`\`\` julia
> julia\> type C{T \<: Integer}
> end
> 
> julia\> C{1}
> ERROR: type: C: in T, expected T\<:Integer, got Int64
> 
> julia\> C{Int}
> C{Int64}
> \`\`\`
> 
> Another related issue is that \`Vararg\` doesn't specify any constraint on the parameter and therefore the following syntax is allowed.
> 
> \`\`\` julia
> julia\> (1...)\[1\]
> 1...
> 
> julia\> typeof((1...)\[1\])
> DataType
> \`\`\`

I wouldn’t be against [introducing `::`](https://github.com/JuliaLang/julia/issues/9580#issuecomment-1416334712) as constraints for non-type type parameters, then a similar shorthand `::Any` could replace `<:Any`, even for types. I’d prefer `isa` over `::` because `isa` and `<:` are also operations that return `true` or `false`, but since `<:` isn’t behaving like that in `where` clauses, I wouldn’t be much uncomfortable with `::` also behaving differently there.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 25, 2024, 1:55pm UTC](https://discourse.julialang.org/t/how-to-skip-type-parameters-in-function-signature/106300/9 "2024-06-25T13:55:41Z")

</div>

I came across this old discussion accidentally, and just want to add for others finding it that this proposal has an issue,

> <https://github.com/JuliaLang/julia/issues/29875>
>
> Consider 
> 
> \`\`\`jl
> struct Foo{A, B, C, D}
> end
> \`\`\`
> 
> and we want to write a b…inary function where \`D\` has to match.
> 
> Possibilities:
> 
> \`\`\`jl
> foo(A::Foo{A1, B1, C1, D}, B::Foo{A2, B2, C2, D}) where {A1, A2, B1, B2, C1, C2, D} = ...
> foo(A::Foo{\<:Any, \<:Any, \<:Any, D}, B::Foo{\<:Any, \<:Any, \<:Any, D}) where {D} = ...
> \`\`\`
> 
> How about:
> 
> \`\`\`jl
> foo(A::Foo{\_, \_, \_, D}, B::Foo{\_, \_, \_, D}) where {D} = ...
> \`\`\`
> 
> ?
> 
> Using \`\_\` as an rvalue is deprecated so could this should be available?
