# Sum types in Julia

**URL:** <https://discourse.julialang.org/t/sum-types-in-julia/2795>\
**Category:** Internals & Design\
**Created:** [March 21, 2017, 4:30pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795 "2017-03-21T16:30:12Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ford](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ford/32/1741_2.png) [@Ford](https://discourse.julialang.org/u/Ford)\
**Post date:** [March 21, 2017, 4:30pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/1 "2017-03-21T16:30:12Z")

</div>

Sum types are great invention that simplify some tasks tremendously - i. e. for handling invalid values, parsing dsl or any data with weird shape in general.

I think [this article](https://chadaustin.me/2015/07/sum-types/) will give a better explanation.

Have Julia authors thought about adding this feature into the language.  
Have they ever worked in a language that provides them?  
What is _your_ opinion?

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [March 21, 2017, 4:41pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/2 "2017-03-21T16:41:14Z")

</div>

[http://julia.readthedocs.io/en/latest/manual/types/#type-unions](http://julia.readthedocs.io/en/latest/manual/types/#type-unions)

---

<div class="post-metadata">

**Author:** ![Ford](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ford/32/1741_2.png) [@Ford](https://discourse.julialang.org/u/Ford)\
**Post date:** [March 21, 2017, 5:37pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/3 "2017-03-21T17:37:38Z")

</div>

Type union is not a sum type although they look similar.

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [March 21, 2017, 5:44pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/4 "2017-03-21T17:44:55Z")

</div>

Maybe you can tell us more about what features of sum types you are particularly interested in? Work is currently going on to optimize storage and dispatch of `Union` types. What would you need more?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 21, 2017, 6:44pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/5 "2017-03-21T18:44:27Z")

</div>

> [@nalimilan](#):
>
> Maybe you can tell us more about what features of sum types you are particularly interested in?

Agreed. I read the description, but it still looks like programming mumbo-jumbo to me. But if you give a super slick example (preferably related to scientific computing 🙂) then I’ll understand it and probably like it.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 21, 2017, 6:51pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/6 "2017-03-21T18:51:49Z")

</div>

> [@Ford](#):
>
> Type union is not a sum type although they look similar.

A type union in Julia is _exactly_ a sum type, according to my understanding. (However, Julia doesn’t have the nice pattern-matching syntax for working with algebraic datatypes that you have in ML etc.)

---

<div class="post-metadata">

**Author:** ![datnamer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datnamer/32/3471_2.png) [@datnamer](https://discourse.julialang.org/u/datnamer)\
**Post date:** [March 21, 2017, 7:08pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/7 "2017-03-21T19:08:48Z")

</div>

What about tagged unions?

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [March 21, 2017, 8:37pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/8 "2017-03-21T20:37:26Z")

</div>

> [@stevengj](#):
>
> However, Julia doesn’t have the nice pattern-matching syntax for working with algebraic datatypes that you have in ML etc

Julia has another kind of “pattern matching” 🙂

```julia
struct ClickEvent
    x::Int
    y::Int
end

struct PaintEvent
    c::Color
end

const Event = Union{ClickEvent, PaintEvent}

handle_event(ev::ClickEvent) = ...
handle_event(ev::PaintEvent) = ...
handle_event(ev) = error("No such event")

```

The only real difference I can see is that Julia unions aren’t closed and not checked during compilation, i.e. there’s no way to prevent a user from creating more event types.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 21, 2017, 10:58pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/9 "2017-03-21T22:58:11Z")

</div>

> [@stevengj](#):
>
> A type union in Julia is exactly a sum type, according to my understanding. (However, Julia doesn’t have the nice pattern-matching syntax for working with algebraic datatypes that you have in ML etc.)

A sum type doesn’t seem to be a type union - and it is a feature that would be very useful in Julia. It has been discussed before for Julia, i.e. called tagged unions, discriminated unions, or tagged variants.  
If you have a type union in Julia, in means you have to have a pointer to a boxed object that has it’s type information,  
which is not the same as being able to have multiple types sharing the same memory, distinguished by a tag.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 22, 2017, 1:25am UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/10 "2017-03-22T01:25:43Z")

</div>

> [@ScottPJones](#):
>
> If you have a type union in Julia, in means you have to have a pointer to a boxed object that has it’s type information,which is not the same as being able to have multiple types sharing the same memory, distinguished by a tag.

That seems like a question of implementation, not semantics. (Do sum types in Haskell or ML make any guarantees about memory representation?)

(In fact, there are ongoing efforts to improve the efficiency of unions of small numbers of types in Julia, driven in part by things like nullable types. It may well be that in a future version of Julia something like `Union{Int,Float64,Void}` will be stored inline (e.g. in an array or a mutable) with a type tag, rather than as a pointer to a heap object.)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 22, 2017, 1:56am UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/11 "2017-03-22T01:56:10Z")

</div>

> [@stevengj](#):
>
> there are ongoing efforts to improve the efficiency of unions of small numbers of types in Julia

For example, see: [https://github.com/JuliaLang/julia/pull/20593](https://github.com/JuliaLang/julia/pull/20593)

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 22, 2017, 5:06am UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/12 "2017-03-22T05:06:37Z")

</div>

> [@stevengj](#):
>
> That seems like a question of implementation, not semantics.

Not really - when talking about tagged unions, the definition is basically that the memory is shared.

“The primary advantage of a tagged union over a simple record containing a field for each type is that it saves storage by overlapping storage for all the types. Some implementations reserve enough storage for the largest type, while others dynamically adjust the size of a tagged union value as needed. When the value is immutable, it is simple to allocate just as much storage as is needed.”

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [March 22, 2017, 5:23am UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/13 "2017-03-22T05:23:08Z")

</div>

There _is_ a semantic difference between sum types and union types, but it is subtle. The difference is that `Sum{Foo, Bar}` contains information about whether it is a left object of type `Foo`, or a right object of type `Bar`. This difference is important when the intersection of `Foo` and `Bar` is non-empty.

For instance, in Haskell:

```haskell
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
Prelude> let foo 0 = Left (); foo n = Right ()
Prelude> let bar (Left _) = "left"; bar (Right _) = "right"
Prelude> foo 0
Left ()
Prelude> foo 1
Right ()
Prelude> bar (foo 0)
"left"
Prelude> bar (foo 1)
"right"

```

whereas a union type loses the left/right information.

From Wikipedia,

> In set theory the equivalent of a sum type is a disjoint union, a set which elements are pairs consisting of a tag (equivalent to a constructor) and an object of a type corresponding to the tag (equivalent to the constructor arguments).

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [March 22, 2017, 5:30am UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/14 "2017-03-22T05:30:56Z")

</div>

However, sum types are easily implemented in a package. Here are some sample implementations.

```julia
struct Left{T}
    val::T
end

struct Right{T}
    val::T
end

const Sum{T, U} = Union{Left{T}, Right{U}}

```

or with a backing `Union`:

```julia
struct Sum{T, U}
    isleft::Bool
    val::Union{T, U}
end

```

or with `Nullable`:

```julia
struct Sum{T, U}
    left::Nullable{T}
    right::Nullable{U}
end

```

or with memory being shared, for primitive types of the same size:

```julia
struct IsBitsSum{T, U}
    isleft::Bool
    bits::T
end

unsafe_left(x::IsBitsSum) = x.bits
unsafe_right(x::IsBitsSum{<:Any, U}) where U = reinterpret(U, x.bits)
left(x::IsBitsSum) = (@argcheck x.isleft; unsafe_left(x))
right(x::IsBitsSum) = (@argcheck !x.isleft; unsafe_right(x))
get(x::IsBitsSum) = x.isleft ? unsafe_left(x) : unsafe_right(x)

```

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 22, 2017, 11:43am UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/15 "2017-03-22T11:43:10Z")

</div>

Tagged pointers I think still would need low-level system support, and this is something very commonly used in C programming (Julia itself uses it internally).  
There would need to be some way of telling julia the mapping between the tag (which might be encoded in the bottom bits of the pointer), and what type the rest of the value is (it might be an integer, or a 61 bit floating point value, or different types of pointers), and have julia be able to know how to follow pointers during marking for GC.

---

<div class="post-metadata">

**Author:** ![pint](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pint/32/125_2.png) [@pint](https://discourse.julialang.org/u/pint)\
**Post date:** [March 22, 2017, 2:10pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/16 "2017-03-22T14:10:14Z")

</div>

isn’t this the same situation as Nullable? with unions, this is ambiguous, and in fact we have functions for A, B and C:

```julia
T1 = Union{A, B}
T2 = Union{A, C}

something(t1::T1) = ... # t1 will be either A or B
something(t2::T2) = ... # t2 will be either A or C

```

however, with an imaginary sum type we would have

```julia
T1 = Sum{A, B}
T2 = Sum{A, C}

something(t1::T1) = ... # t1 will be Sum{A, B}, and can be queried which value is set
something(t2::T2) = ... # t2 will be Sum{A, C}

```

so there is semantic difference. note that i’m not arguing that Julia needs a sum type. just trying to see what it gives.

---

<div class="post-metadata">

**Author:** ![andyferris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andyferris/32/235_2.png) [@andyferris](https://discourse.julialang.org/u/andyferris)\
**Post date:** [March 22, 2017, 9:20pm UTC](https://discourse.julialang.org/t/sum-types-in-julia/2795/17 "2017-03-22T21:20:10Z")

</div>

I played with explicitly tagged types here: [https://github.com/andyferris/Switches.jl](https://github.com/andyferris/Switches.jl)

However, I stopped developing it once I realized @jameson was keen to make (implicitly tagged, by the compiler) `Union` types work faster…
