# Julia types

**URL:** <https://discourse.julialang.org/t/julia-types/62352>\
**Category:** New to Julia\
**Created:** [June 3, 2021, 7:34pm UTC](https://discourse.julialang.org/t/julia-types/62352 "2021-06-03T19:34:25Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jinml](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@jinml](https://discourse.julialang.org/u/jinml)\
**Post date:** [June 3, 2021, 7:34pm UTC](https://discourse.julialang.org/t/julia-types/62352/1 "2021-06-03T19:34:25Z")

</div>

Hi I am studying Julia’s type system and was confused about parametric types. In the juliadocs there is the following example

```julia
struct Point{T} 
x::T
y::T
end

```

and if I would like to restrict _T_ to \<:Real I do the following

```julia
struct Point{T<:Real} 
x::T
y::T
end

```

but I cannot do this

```julia
struct Point{T where T<:Real} 
x::T
y::T
end

```

or

```julia
struct Point{T} where T<:Real
x::T
y::T
end

```

what is wrong with it? Moreover, if for whatever reason, this is what I intend to do

```julia
struct Point{T,S} where S<:Real, T<:S
x::T
y::S
end

```

how should I do it?

A few other related questions (suppose T, S, etc. are declared types):

1. `Union{T,S} isa Union`, but not a `DataType`, why?
2. `Union isa Type` and `Union<:Type` are both true, So is `Union` an object of `Type`, or a `subtype` of `Type`? Similiarly `Union isa DataType` is true, but `Union<:DataType` is false, what is the rationale?
3. `Type isa Type` is true, but `T isa T` is false. what’s the rationale?
4. What is the general framework of all these rules? Is it consistent?

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [June 3, 2021, 8:49pm UTC](https://discourse.julialang.org/t/julia-types/62352/2 "2021-06-03T20:49:41Z")

</div>

You can write

```julia
struct Point{S<:Real, T<:S}
    x::T
    y::S
end

```

Maybe weird, but c’est la vie. Alternatively, you can enforce field type relationships in an inner constructor:

```julia
struct Point{T,S<:Real}
    x::T
    y::S
    function Point{T,S}(x, y) where {S<:Real, T<:S}
        return new{T,S}(x, y)
    end
end

```

Furthers answers, as per my understanding:

1. There are 3 “kinds” of types (`subtypes(Type)`, excluding `Core.TypeofBottom`): `DataType`, `Union` and `UnionAll`. The first includes all normal concrete and abstract types. The second includes all unions of a finite number of types. The third includes constructs like `Vector{T} where {T<:Any}`.
2. `Type` is a supertype of all type objects. `Union` is a supertype for all union type objects, but it is also an object of `DataType`. Thus, `Union` is a subtype of `Type`, and its type is also a subtype of `Type`.  
`Union isa DataType` means `typeof(Union) <: DataType` (i.e. `Union` as an object has a type which is in the `DataType` subtree). `Union <: DataType` is just false, they are on different branches of type hierarchy.
3. Same as previous. `T isa T` is not true in general because, e.g., `Int` is not an integer number, it is a type.
4. The best source I am aware of is [this paper](https://hal.inria.fr/hal-01882137/document).

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 3, 2021, 9:22pm UTC](https://discourse.julialang.org/t/julia-types/62352/3 "2021-06-03T21:22:07Z")

</div>

```julia
struct Point{T} where T<:Real
x::T
y::T
end

```

Do you know if this syntax is invalid for some functional, or historic/implementation-details reason?

---

<div class="post-metadata">

**Author:** ![jinml](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@jinml](https://discourse.julialang.org/u/jinml)\
**Post date:** [June 4, 2021, 1:09am UTC](https://discourse.julialang.org/t/julia-types/62352/4 "2021-06-04T01:09:29Z")

</div>

> [@Vasily\_Pisarev](#):
>
> The best source I am aware of is [this paper](https://hal.inria.fr/hal-01882137/document).

Thanks for pointing me to this paper. I am far from being a CS person, but attempted to understand this part of the paper:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/2/b/2be2ecedbc77c8abf6605606d8f94a87b942318a.png)  
is there a mistake in the second case, where instead of `t[t3/T]<:t'`, what it means should be `t'<:t[t3/T]`?  
I am not a CS person so I may be grossly off in my understanding …

---

<div class="post-metadata">

**Author:** ![ptoche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ptoche/32/23554_2.png) [@ptoche](https://discourse.julialang.org/u/ptoche)\
**Post date:** [June 4, 2021, 4:29am UTC](https://discourse.julialang.org/t/julia-types/62352/5 "2021-06-04T04:29:26Z")

</div>

The whole history can be reconstructed from various discussions linked [here](https://discourse.julialang.org/t/anybody-else-find-the-new-where-syntax-less-than-satisfactory/4897/14). I haven’t read everything, but [this explanation](https://stackoverflow.com/questions/41931289/where-in-function-definitions-in-julia-0-6/41940710#41940710) is a good one-stop.

Let me quote an excerpt from [Stefan’s explanation](https://discourse.julialang.org/t/anybody-else-find-the-new-where-syntax-less-than-satisfactory/4897/14):

> In Julia 1.0, on the other hand, type parameters and constructors will be thoroughly consistent, following these general principles uniformly:
> 
> - The syntax used to define a method _always_ matches the syntax used to call it.
> - The `F{T}` syntax _always_ refers to the type `F` with parameter value `T` .
> - Type parameters are _always_ introduced by `where` clauses.
> 
> I think these principles make the syntax and semantics of parametric types and methods far more understandable and intuitive. Given these principles, semantics like what we now have seem inevitable. The only real question is syntax – and what syntax to use was one of the biggest bikesheds around this issue. I wasn’t initially thrilled with the postfix `where` syntax, but it’s grown on me and now it seems quite natural. The only really odd case, as you mention, is `f(...) where T = body` without any type bound, but I’ve found that even this case fairly quickly loses its unfamiliarity. Other keywords than `where` were discussed, including `forall` and `∀` . However, Julia’s “union all” types are _not_ universally quantified types (they’re actually closer to existentially quantified types), so both of these choices would have been actively at odds with existing type theory nomenclature. The `where` keyword was the most evocative choice proposed that didn’t clash with well-established terminology. Finally, having the `where` clause on the right just seemed to read much more naturally in the vast majority of usages.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [June 4, 2021, 5:47am UTC](https://discourse.julialang.org/t/julia-types/62352/6 "2021-06-04T05:47:33Z")

</div>

But that quote is inaccurate. You cannot use `where` syntax to define parametric types.

I am also curious as to why.

---

<div class="post-metadata">

**Author:** ![ptoche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ptoche/32/23554_2.png) [@ptoche](https://discourse.julialang.org/u/ptoche)\
**Post date:** [June 4, 2021, 6:17am UTC](https://discourse.julialang.org/t/julia-types/62352/7 "2021-06-04T06:17:18Z")

</div>

> [@gustaphe](#):
>
> You cannot use `where` syntax to define parametric types.

I see what you mean. When I pulled the quote I was more focused on why the `where` keyword was introduced. For consistency it would make sense to have imposed it for `struct`s too…

---

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [June 4, 2021, 7:10am UTC](https://discourse.julialang.org/t/julia-types/62352/8 "2021-06-04T07:10:13Z")

</div>

> [@lmiq](#):
>
> ```julia
> struct Point{T} where T<:Real
> x::T
> y::T
> end
> 
> ```
> 
> Do you know if this syntax is invalid for some functional, or historic/implementation-details reason?

My best guess is that the `{...}` in a type definition `struct MyType{...}` is roughly equivalent to the part _after_ the `where` in a function definition, and `where` constructs are disallowed in this place:

```julia
julia> struct Foo{T where T}
           x::T
       end
ERROR: syntax: invalid variable expression in "where"

julia> foo(x::T) where {T where T} = x
ERROR: syntax: invalid variable expression in "where"

```

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [June 4, 2021, 7:36am UTC](https://discourse.julialang.org/t/julia-types/62352/9 "2021-06-04T07:36:08Z")

</div>

That’s not very convincing to me. There is nothing `where`-y about it.

```julia
a = :(struct Foo{T} where T end)
a.args[2].head == :where
b = :(struct Foo{T<:Any} end)
b.args[2].head == :curly

```

So they are definitely syntactically separated.

---

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [June 4, 2021, 7:43am UTC](https://discourse.julialang.org/t/julia-types/62352/10 "2021-06-04T07:43:38Z")

</div>

The point is that the `{T}` in `struct Foo{T}` serves the same purpose as the `{T}` after the `where` in `function foo(::T) where {T}`: in both cases, the `{T}` indicates that the compiler should treat `T` as a type variable. Writing `{T where T}` in this position does not make sense because `T where T` is not a valid type variable symbol.

Similarly, `struct Foo{T} where T end` does not make sense because you already introduced `T` as a type variable in the `Foo{T}` part.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 4, 2021, 8:55am UTC](https://discourse.julialang.org/t/julia-types/62352/11 "2021-06-04T08:55:29Z")

</div>

This is just me shooting from the hip, I don’t really understand the deeper reasons here, but to me, these two are analogous:

```julia
function foo(x::Number) end
struct Foo{X<:Number} end

```

And the reason you need the `where` clause for functions is that you need some way to provide the subtyping information that doesn’t fit in the function signature:

```julia
function foo(x::X) where {X<:Number}

```

For structs, this isn’t necessary, or makes no sense, because it fits right in the struct signature.

It used to be that signatures looked like this

```julia
function foo{X<:Number}(x::X)

```

but that caused problems for type constructors (and some other stuff).

---

<div class="post-metadata">

**Author:** ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)\
**Post date:** [June 4, 2021, 9:48am UTC](https://discourse.julialang.org/t/julia-types/62352/12 "2021-06-04T09:48:11Z")

</div>

> [@DNF](#):
>
> I don’t really understand the deeper reasons here,

what bou

```julia

function foo(x::SomeType{T}) where T

```

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [June 4, 2021, 10:54am UTC](https://discourse.julialang.org/t/julia-types/62352/13 "2021-06-04T10:54:42Z")

</div>

The [documentation](https://docs.julialang.org/en/v1/manual/types/#man-parametric-composite-types) also mentions the form

```julia
function norm(p::Point{T} where T<:Real)

```

Does that lead to a different function than

```julia
function norm(p::Point{T}) where T<:Real

```

or is it just a different form of writing it?

Edit: seems these are equivalent as it overwrites the existing method:

```julia
julia> function norm(p::Point{T}) where T<:Real
           sqrt(p.x^2+p.y^2)
       end
norm (generic function with 1 method)

julia> methods(norm)
# 1 method for generic function "norm":
[1] norm(p::Point{T}) where T<:Real in Main at REPL[8]:1

julia> function norm(p::Point{T} where T<:Real)
           sqrt(p.x^2+p.y^2)
       end
norm (generic function with 1 method)

julia> methods(norm)
# 1 method for generic function "norm":
[1] norm(p::Point{T} where T<:Real) in Main at REPL[10]:1

```

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [June 4, 2021, 11:12am UTC](https://discourse.julialang.org/t/julia-types/62352/14 "2021-06-04T11:12:33Z")

</div>

Hm. I guess it’s reasonable that `struct F{T} where T<:Int` would be comparable to `struct F{Int}` which is not the same as `struct F{T<:Int}`.

I still think that this is essentially free syntax, and it would be very handy for clearing up type signatures. But maybe it’s better to not introduce confusion about this slight nuance.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 4, 2021, 12:52pm UTC](https://discourse.julialang.org/t/julia-types/62352/15 "2021-06-04T12:52:09Z")

</div>

> [@gustaphe](#):
>
> I guess it’s reasonable that `struct F{T} where T<:Int` would be comparable to `struct F{Int}`

I think that `struct F{T} where T<:Int` would be comparable to

```julia
function f(t) where t::Int

```

which also doesn’t work.

---

<div class="post-metadata">

**Author:** ![jinml](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@jinml](https://discourse.julialang.org/u/jinml)\
**Post date:** [June 4, 2021, 1:59pm UTC](https://discourse.julialang.org/t/julia-types/62352/16 "2021-06-04T13:59:11Z")

</div>

> [@jinml](#):
>
> Thanks for pointing me to this paper. I am far from being a CS person, but attempted to understand this part of the paper:
> 
> ![image](https://global.discourse-cdn.com/julialang/original/3X/2/b/2be2ecedbc77c8abf6605606d8f94a87b942318a.png)
> 
> is there a mistake in the second case, where instead of `t[t3/T]<:t'` , what it means should be `t'<:t[t3/T]` ?  
> I am not a CS person so I may be grossly off in my understanding …

Thank you all for the historical info. Could you guys take a look at the quoted paper and help with the question I had in post #3? Thanks.  
Btw, does A\<:B and B\<:A imply A==B?

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [June 4, 2021, 5:40pm UTC](https://discourse.julialang.org/t/julia-types/62352/17 "2021-06-04T17:40:23Z")

</div>

> [@paulmelis](#):
>
> Edit: seems these are equivalent as it overwrites the existing method:
> 
> ```julia
> julia> function norm(p::Point{T}) where T<:Real
> sqrt(p.x^2+p.y^2)
> end
> norm (generic function with 1 method)
> 
> julia> methods(norm)
> # 1 method for generic function "norm":
> [1] norm(p::Point{T}) where T<:Real in Main at REPL[8]:1
> 
> julia> function norm(p::Point{T} where T<:Real)
> sqrt(p.x^2+p.y^2)
> end
> norm (generic function with 1 method)
> 
> julia> methods(norm)
> # 1 method for generic function "norm":
> [1] norm(p::Point{T} where T<:Real) in Main at REPL[10]:1
> 
> ```

They’re not quite equivalent; the scope of `T` differs between the two cases:

```julia
julia> foo(::T where T) = T
foo (generic function with 1 method)

julia> bar(::T) where T = T
bar (generic function with 1 method)

julia> foo(1)
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] foo(#unused#::Int64)
   @ Main ./REPL[1]:1
 [2] top-level scope
   @ REPL[3]:1

julia> bar(1)
Int64

```

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [June 4, 2021, 7:06pm UTC](https://discourse.julialang.org/t/julia-types/62352/18 "2021-06-04T19:06:24Z")

</div>

> [@StevenWhitaker](#):
>
> They’re not quite equivalent; the scope of `T` differs between the two cases:
> 
> ```julia
> julia> foo(::T where T) = T
> foo (generic function with 1 method)
> 
> julia> bar(::T) where T = T
> bar (generic function with 1 method)
> 
> julia> foo(1)
> ERROR: UndefVarError: T not defined
> Stacktrace:
> [1] foo(#unused#::Int64)
> @ Main ./REPL[1]:1
> [2] top-level scope
> @ REPL[3]:1
> 
> julia> bar(1)
> Int64
> 
> ```

Is there any way with the first form to reuse the `T` parameter? E.g. this doesn’t work:

```julia
julia> foo(x::T where T, y::T) = x+y
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] top-level scope
   @ REPL[1]:1

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 4, 2021, 7:48pm UTC](https://discourse.julialang.org/t/julia-types/62352/19 "2021-06-04T19:48:33Z")

</div>

> [@paulmelis](#):
>
> Is there any way with the first form to reuse the `T` parameter?

Nope, that’s the point. It’s a little like asking for this to work:

```julia
julia> let
           let
               x = 1
           end
           x + 1
       end
ERROR: UndefVarError: x not defined
Stacktrace:
 [1] top-level scope
   @ REPL[3]:5

```

The answer is to pull `x` out of the inner scope into the outer one.

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [June 4, 2021, 7:53pm UTC](https://discourse.julialang.org/t/julia-types/62352/20 "2021-06-04T19:53:24Z")

</div>

> [@paulmelis](#):
>
> Is there any way with the first form to reuse the `T` parameter?

Not that I’m aware of. In the first form, `T` has very limited scope.

Here are some additional examples that might help clarify how scoping works with type declarations.

```julia
julia> foo(x::Union{T,Vector{T}} where T) = eltype(x) # Works
foo (generic function with 1 method)

julia> foo(x::Union{T,Vector{T} where T}) = eltype(x)
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] top-level scope
   @ REPL[2]:1

julia> foo(x::Union{T where T, Vector{T}}) = eltype(x)
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

julia> foo(x::Union{T where T, Vector{T} where T}) = eltype(x) # Also works, each T is different
foo (generic function with 1 method)

```

[Next page](https://discourse.julialang.org/t/julia-types/62352.md?page=2)
