# Make \`Type{}\` "covariant"

**URL:** <https://discourse.julialang.org/t/make-type-covariant/900>\
**Category:** Internals & Design\
**Created:** [December 12, 2016, 7:57pm UTC](https://discourse.julialang.org/t/make-type-covariant/900 "2016-12-12T19:57:16Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 12, 2016, 7:57pm UTC](https://discourse.julialang.org/t/make-type-covariant/900/1 "2016-12-12T19:57:16Z")

</div>

This is probably a stupid question: couldn’t `Type` behave covariantly? So, e.g. `Type{Int}<:Type{Integer}`. As `Type` can never be instantiated, the usual road-blocks for covariance do not apply. Also `Type` is pretty special already, so being more special shouldn’t come as too much of a surprise.

Then this would work:

```julia
f{T}(::Type{AbstractArray{T,1}}) = T
f(Range{Int}) # -> Int

```

instead of the [parameter juggle](https://github.com/JuliaLang/julia/pull/19306/files#diff-78f2e86ca66ebcee42787a87d298c710R457) needed currently (this gets better with the type-overhaul but above would still be useful).

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [December 12, 2016, 8:02pm UTC](https://discourse.julialang.org/t/make-type-covariant/900/2 "2016-12-12T20:02:57Z")

</div>

> [@mauro3](#):
>
> Type{Int}\<:Type{Integer}

This doesn’t sound right `T1 <: T2` means that if `isa(v1, T1)` then `isa(v1, T2)` However, `isa(Int, Type{Int})` but `!isa(Int, Type{Integer})`.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 12, 2016, 8:18pm UTC](https://discourse.julialang.org/t/make-type-covariant/900/3 "2016-12-12T20:18:11Z")

</div>

Yes, to make `isa(Int, Type{Integer})==true` is the essence of the proposal.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [December 12, 2016, 8:20pm UTC](https://discourse.julialang.org/t/make-type-covariant/900/4 "2016-12-12T20:20:04Z")

</div>

> [@mauro3](#):
>
> make isa(Int, Type{Integer})==true

This will be a major breaking change since then `f(::Type{Integer})` will have the same meaning as `f{T<:Integer}(::Type{T})` and being able to distinguish the two is a important reason why `Type` is useful.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 12, 2016, 8:30pm UTC](https://discourse.julialang.org/t/make-type-covariant/900/5 "2016-12-12T20:30:52Z")

</div>

Yes, it would be breaking for sure. Note though that with the current dispatch rules your latter function would win over the former when called with `f(Int)`, thus the distinction could still be made. Here the not quite analogous example with `Tuple`:

```julia
julia> f(::Tuple{Integer}) = 1
f (generic function with 1 method)

julia> f{T<:Integer}(::Tuple{T}) = 2
f (generic function with 2 methods)

julia> f((3,))
2

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [December 12, 2016, 8:56pm UTC](https://discourse.julialang.org/t/make-type-covariant/900/6 "2016-12-12T20:56:53Z")

</div>

I believe that behavior is a bug.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [December 12, 2016, 9:07pm UTC](https://discourse.julialang.org/t/make-type-covariant/900/7 "2016-12-12T21:07:12Z")

</div>

> [@yuyichao](#):
>
> I believe that behavior is a bug.

And just to prove the point, this behavior is fixed on the jb/subtype branch and the two methods are treated as the same one and overwrites each other.

```julia
               _
   _ _ _(_)_ | A fresh approach to technical computing
  (_) | (_) (_) | Documentation: http://docs.julialang.org
   _ _ _| |_ __ _ | Type "?help" for help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 0.6.0-dev.1562 (2016-12-12 21:00 UTC)
 _/ |\ __'_|_|_|\__'_| | jb/subtype/d514ed4* (fork: 18 commits, 1 day)
|__/ | x86_64-pc-linux-gnu

julia> f(::Integer) = 1
f (generic function with 1 method)

julia> f{T<:Integer}(::T) = 2
WARNING: Method definition f(T) in module Main at REPL[1]:1 overwritten at REPL[2]:1.
f (generic function with 1 method)

julia> f2(::Tuple{Integer}) = 1
f2 (generic function with 1 method)

julia> f2{T<:Integer}(::Tuple{T}) = 2
WARNING: Method definition f2(Tuple{T}) in module Main at REPL[3]:1 overwritten at REPL[4]:1.
f2 (generic function with 1 method)

```

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 12, 2016, 9:19pm UTC](https://discourse.julialang.org/t/make-type-covariant/900/8 "2016-12-12T21:19:58Z")

</div>

Yep, that kills it. Thanks @yuyichao for your time to discuss this.
