The Type System
13.1 Concepts
Every value has a concrete type; types form a tree rooted at Any.
Abstract types (Number, Real, AbstractArray) can't be instantiated; they organize the hierarchy.
Concrete types (Int64, Float64, Vector{Int}) are leaves — they can't be subtyped.
Types are first-class values.
Type annotations (::T) are optional; used for dispatch, documentation, and assertions — not usually needed for speed.
Any
├── Number
│ ├── Real
│ │ ├── Integer
│ │ │ ├── Signed (Int8 … Int128, BigInt)
│ │ │ ├── Unsigned (UInt8 … UInt128)
│ │ │ └── Bool
│ │ ├── AbstractFloat (Float16, Float32, Float64, BigFloat)
│ │ ├── Rational
│ │ └── AbstractIrrational (π, ℯ)
│ └── Complex
├── AbstractString (String, SubString)
├── AbstractArray (Array, ranges, SubArray, …)
├── Function
└── … Nothing, Missing, Symbol, Tuple, …supertype(Int64) # Signed
subtypes(Integer) # [Bool, Signed, Unsigned]
Int64 <: Integer # true (subtype)
Integer >: Int64 # true
isconcretetype(Int), isabstracttype(Real)
Union{Int, String} # union type
Union{} # bottom type (no values)
Nothing, Missing # singleton types13.2 Declaring abstract types
abstract type Shape end
abstract type Polygon <: Shape end13.3 Parametric types
Vector{Int} <: Vector{Integer} # false — Julia's parametric types are INVARIANT
Vector{Int} <: Vector{<:Integer} # true (UnionAll / where syntax)
Vector{<:Real} # = Vector{T} where T<:Real
f(v::Vector{T}) where {T<:Number} = sum(v) / length(v)
Array{Float64, 2} === Matrix{Float64}13.4 Type assertions & declarations
x = 1.5::Float64 # assertion (TypeError if wrong)
function g()
y::Float64 = 1 # declaration: values converted to Float64
y
end13.5 Type aliases, unions, singletons
const IntOrString = Union{Int, String}
const Maybe{T} = Union{T, Nothing}
struct Red end # singleton type: Red() has no fields
Val(3) # value types for dispatch on values: f(::Val{3}) = "three"