# What's with the invariant parametric types gotcha?

**URL:** <https://discourse.julialang.org/t/whats-with-the-invariant-parametric-types-gotcha/55090>\
**Category:** New to Julia\
**Created:** [February 11, 2021, 8:32pm UTC](https://discourse.julialang.org/t/whats-with-the-invariant-parametric-types-gotcha/55090 "2021-02-11T20:32:29Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![DevJac](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@DevJac](https://discourse.julialang.org/u/DevJac)\
**Post date:** [February 11, 2021, 8:32pm UTC](https://discourse.julialang.org/t/whats-with-the-invariant-parametric-types-gotcha/55090/1 "2021-02-11T20:32:29Z")

</div>

Consider:

```julia
julia> foo(x::Vector{Integer}) = "bar"
foo (generic function with 1 method)

julia> foo([1, 2, 3])
ERROR: MethodError: no method matching foo(::Array{Int64,1})
Closest candidates are:
  foo(::Array{Integer,1}) at REPL[1]:1
Stacktrace:
 [1] top-level scope at REPL[2]:1

julia> foo(x::Vector{<:Integer}) = "bar"
foo (generic function with 2 methods)

julia> foo([1, 2, 3])
"bar"

```

Of course, this is documented: [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#Parametric-Composite-Types)

Still, in my mind I could almost audibly hear Julia saying “ha ha, gotcha!” when I first learned this. What is the reason for this syntax?

Is it even possible to call `foo(x::Vector{Integer}) = "bar"`? If not, why not just implicitly add the `<:` syntax so it “just works”?

Is it just a syntax decision? Maybe the designers of the language wanted to be explicit by requiring the `<:` syntax? If so, that’s understandable, even though I may or may not agree\*.

\* I don’t agree or disagree with any syntax decisions. I like Julia, and I like its syntax. And in general I consider syntax issues to be very low on the list of things that matter, so I don’t even bother forming an opinion on most syntax debates.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [February 11, 2021, 8:43pm UTC](https://discourse.julialang.org/t/whats-with-the-invariant-parametric-types-gotcha/55090/2 "2021-02-11T20:43:16Z")

</div>

> [@DevJac](#):
>
> Is it even possible to call `foo(x::Vector{Integer}) = make_sandwich()` ?

Yes. Just call:

```julia
foo(Integer[1, 2, 3])

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [February 11, 2021, 8:45pm UTC](https://discourse.julialang.org/t/whats-with-the-invariant-parametric-types-gotcha/55090/3 "2021-02-11T20:45:19Z")

</div>

> [@DevJac](#):
>
> Is it just a syntax decision?

No, the syntax really isn’t the core of the issue here. A `Vector{Integer}` is a real type, and one you might even use at some point, it’s just that `[1, 2, 3]` doesn’t give you one.

A `Vector{Integer}` is a vector in which every element can be a (potentially different) subtype of `Integer`:

```julia
julia> x = Vector{Integer}()
Integer[]

julia> push!(x, 1)
1-element Array{Integer,1}:
 1

julia> push!(x, big(2)^big(100))
2-element Array{Integer,1}:
                               1
 1267650600228229401496703205376

```

This is different from `Vector{Int64}` in which every element is exactly the concrete type `Int64`. It’s also different from `Vector{<:Integer}` which is a _set_ of types describing any `Vector` whose element type is any subtype of `Integer`. `Vector{Int64}` and `Vector{Integer}` are both members of that set:

```julia
julia> Vector{Int64} <: Vector{<:Integer}
true

julia> Vector{Integer} <: Vector{<:Integer}
true

```

but they have no relationship to one another otherwise:

```julia
julia> Vector{Int64} <: Vector{Integer}
false

```

```julia

```

---

<div class="post-metadata">

**Author:** ![DevJac](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@DevJac](https://discourse.julialang.org/u/DevJac)\
**Post date:** [February 11, 2021, 8:45pm UTC](https://discourse.julialang.org/t/whats-with-the-invariant-parametric-types-gotcha/55090/4 "2021-02-11T20:45:36Z")

</div>

I see. So there is at least a reason for the syntax. Because you need some way to distinguish between, well, a `Vector{Integer}` and a `Vector{<:Integer}`. I’m satisfied with that explanation.
