Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why union type not accepting one of its types in Julia?

Tags:

julia

Why union type Array{Union{Missing, Float64},1} is not accepting Array{Float64,1}

function somefn(; serie::Vector{Union{Missing, Float64}})
end
serie = [1.0, 2.0, 1.0, 4.0]
somefn(serie = serie)


ERROR: TypeError: in keyword argument serie, expected Array{Union{Missing, Float64},1}, got Array{Float64,1}
Stacktrace:
 [1] (::var"#kw##somefn")(::NamedTuple{(:serie,),Tuple{Array{Float64,1}}}, ::typeof(somefn)) at ./none:0
 [2] top-level scope at REPL[12]:1

One way to fix it is to remove Vector{Union{Missing, Float64}} from function signature, I don't want to do that, I want to explicitly limit possible types for function arguments to reduce the bugs and easier understand how function works.

like image 470
Alex Craft Avatar asked Jan 18 '20 06:01

Alex Craft


People also ask

What is Union in Julia?

Type Unions A type union is a special abstract type which includes as objects all instances of any of its argument types, constructed using the special Union keyword: julia> IntOrString = Union{Int,AbstractString} Union{Int64, AbstractString} julia> 1 :: IntOrString 1 julia> "Hello!" :: IntOrString "Hello!"

What is abstract type in Julia?

Abstract types allow the construction of a hierarchy of types, providing a context into which concrete types can fit. This allows you, for example, to easily program to any type that is an integer, without restricting an algorithm to a specific type of integer.

What is mutable struct in Julia?

type and immutable are valid up to julia 0.6, mutable struct and struct are the names of the same objects in julia 0.6 and forward. mutable in mutable struct means that the fields can change - which is actually fairly rarely used so being immutable is the default. mutable struct 's are slower than struct s.


1 Answers

The reason is explained in The Julia Manual in the section on Parametric Composite Types.

In short in Julia types, except tuples are invariant. Citing the documentation:

This last point is very important: even though Float64 <: Real we DO NOT have Point{Float64} <: Point{Real}.

The way to fix your code to work is to write either:

function somefn(; serie::Vector{<:Union{Missing, Float64}})
end

or

function somefn(; serie::Vector{T}) where {T<:Union{Missing, Float64}}
end

which is explained later in that section of the manual.

The key thing to understand is that Vector{<:Union{Missing, Float64}} matches all types whose parameter is a subtype of Union{Missing, Float64}, whereas in Vector{Union{Missing, Float64}} the parameter must match Union{Missing, Float64} exactly.

Therefore in your original code example the following call:

somefn(serie = Union{Float64,Missing}[1,2,3])

would work as type parameter would match.

like image 55
Bogumił Kamiński Avatar answered Nov 15 '22 08:11

Bogumił Kamiński