# The expression solution

**URL:** https://discourse.julialang.org/t/the-expression-solution/103435
**Category:** Internals & Design
**Tags:** question
**Created:** [September 1, 2023, 7:52am UTC](https://discourse.julialang.org/t/the-expression-solution/103435 "2023-09-01T07:52:40Z")
**Posts on this page:** 12
**Page:** 2

<div class="post-metadata">

### Author: ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)
#### Post date: [September 1, 2023, 6:01pm UTC](https://discourse.julialang.org/t/the-expression-solution/103435/21 "2023-09-01T18:01:14Z")

</div>

> [@Sukera](#):
>
> No, why would it? SumTypes.jl and others don’t change existing functions. They let _you_ enforce those semantics in your code. It’s a package like any other.

Thanks a lot about your explanation. What I am still struggling to understand, is how the inclusion of sum type in the language, would automatically lead to _Base_ being required to handle the `nothing` case of `findfirst`.

It is, what I understood would happen, and I don’t quite get, how these two things are related?  
Why would we be unable, to implement that language feature without touching that?

> [@bertschi](#):
>
> In dynamic languages such as Julia, Python or Common Lisp, you won’t get such help anyway and thus, untagged unions are more common

I wonder why everyone here seems to see Julia as a dynamic language, while it seems to me, that it is designed to be dynamic and statically typed, depending on the requirement, situation, and preference.

It seems, to me, a lost opportunity to present this rare language feature, that is, for whatever reason, not very widely available. Julia being effectively a gradually typed language seems to be one of its core appeals to me.

And that would also showcase the usability and practicality of sum types to – as some of you have said – complement Julia’s approach to the expression problem.

---

<div class="post-metadata">

### Author: ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)
#### Post date: [September 1, 2023, 6:33pm UTC](https://discourse.julialang.org/t/the-expression-solution/103435/22 "2023-09-01T18:33:32Z")

</div>

If we added SumTypes to Base, we wouldn’t be able to do much with them within the language without breaking changes. It doesn’t matter how many people use `findfirst`. All that matters is that, right now, the docs say that it will return a valid index or `nothing`. So if you change it to return `SumType{Int,Nothing}` or whatever, that would be a breaking change.

That’s true for basically ALL public api right now. So you couldn’t implement it in Base, it would just be a tool for User Land… but if that’s the case, why not keep it a package where it can iterate faster and be less concerned with breaking changes while we (… er… @Mason 😅 ) work out how sum types should be implemented.

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [September 1, 2023, 7:37pm UTC](https://discourse.julialang.org/t/the-expression-solution/103435/23 "2023-09-01T19:37:57Z")

</div>

> [@ShalokShalom](#):
>
> I wonder why everyone here seems to see Julia as a dynamic language, while it seems to me, that it is designed to be dynamic and statically typed, depending on the requirement, situation, and preference.

Probably because its semantics is mostly dynamic, i.e., types are not checked at compile time and dispatch is based on runtime type. Further, types are attached to values and not expressions. It gets a hybrid feel though due to its performance optimization to dispatch statically if all types can be inferred at compile-time. This is admittedly very clever as it keeps the language semantics dynamic while running at the speed of compiled ones.  
Imho, sum types are most useful if checked at compile-time – which Julia doesn’t do. Otherwise, untagged unions are just as fast when being constant propagated – which Julia does. What other use cases would you have in mind, where the following would be needed or sufficiently better:

```julia
d = Dict(:a => 1, :b => 2)

# Untagged union
dynget(d, k) = get(d, k, missing)

let v = dynget(d, :c)
    if ismissing(v)
        "handle failure here"
    else
        "do something with $v here"
    end
end

@show Base.return_types(dynget, (typeof(d), typeof(:a)))

# Tagged union
abstract type Option{T} end
struct NoVal{T} <: Option{T} # Note that NoVal is still typed!
end
struct Val{T} <: Option{T}
    val::T
end
function safeget(d::Dict{K,V}, k::K) where {K,V}
    if haskey(d, k)
        Val{V}(d[k])
    else
        NoVal{V}()
    end
end

let v = safeget(d, :c)
     if v isa NoVal
         "handle failure"
     elseif v isa Val
         "do something with $(v.val)"
     end
end

```

---

<div class="post-metadata">

### Author: ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)
#### Post date: [September 1, 2023, 7:46pm UTC](https://discourse.julialang.org/t/the-expression-solution/103435/24 "2023-09-01T19:46:42Z")

</div>

> [@bertschi](#):
>
> Imho, sum types are most useful if checked at compile-time – which Julia doesn’t do.

`JET.@report_call` detects inexhaustive `@cases` in SumTypes.jl.

```julia
julia> using SumTypes

julia> @sum_type Color begin
       Red
       Green
       end

julia> f(x) = @cases x begin
       Red => 1
       Green => 2
       end
f (generic function with 1 method)

julia> @report_call f(Red)
No errors detected

julia> g(x) = @cases x begin
       Red => 1
       end
g (generic function with 1 method)

julia> @report_call g(Red)
═════ 1 possible error found ═════
...
││ Inexhaustive @cases specification. Got cases (:Red,), expected (:Red, :Green): SumTypes.assert_exhaustive(::Type{Val{(:Red, :Green)}}, ::Type{Val{(:Red,)}})
│└────────────────────
```

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [September 1, 2023, 8:55pm UTC](https://discourse.julialang.org/t/the-expression-solution/103435/25 "2023-09-01T20:55:07Z")

</div>

Nice, thanks. That makes them more useful indeed.  
Another use case that just came to my mind, would be a sum type for the cases of an `Expr`. Might make it easier to cover all cases when writing complex macros (which is a bit annoying without something like pattern matching or `MacroTools`’s `@capture` anyways).

---

<div class="post-metadata">

### Author: ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)
#### Post date: [September 2, 2023, 8:23pm UTC](https://discourse.julialang.org/t/the-expression-solution/103435/26 "2023-09-02T20:23:14Z")

</div>

I really like this implementation at a first glance:

> **[Defining algebra data types | Expronicon](https://expronicon.rogerluo.dev/intro/adts/defining/)**
>
> Collective tools for metaprogramming in Julia.

It’s written by a friend of the author from MLStyle.jl

And he has a video about it, here:

[![](https://global.discourse-cdn.com/julialang/original/3X/d/f/df1695a88762912a88c7b0e881199849f071baa8.jpeg "Expronicon: a modern toolkit for meta-programming in Julia | Xiu-zhe (Roger) Luo | JuliaCon 2023") ](https://www.youtube.com/watch?v=F_DjmwyD4O4)

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [September 2, 2023, 10:42pm UTC](https://discourse.julialang.org/t/the-expression-solution/103435/27 "2023-09-02T22:42:13Z")

</div>

I’m not really seeing how sum types solve the expression problem. Functional languages are good at adding new operations to existing types and bad at applying existing operations to new types. How do sum types help functional languages apply existing operations to new types? The classic solution to the expression problem in Haskell, as I understand it, is type classes, not sum types.

---

<div class="post-metadata">

### Author: ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)
#### Post date: [September 3, 2023, 8:53am UTC](https://discourse.julialang.org/t/the-expression-solution/103435/28 "2023-09-03T08:53:58Z")

</div>

Lots of languages use multiple constructs, to solve the different aspects of the expression problem.

Sum types are one part of this. Julia is rare, as it solved the whole issue with one language feature.

Haskell is using type classes and sum types, to achieve this.

F# has no type classes – or anything comparable – and still does utilize sum types.  
There they are called discriminated unions.

> **[Solving the Expression Problem in any language](https://dev.to/kspeakman/solving-the-expression-problem-in-any-language-289m)**
>
> ...and still failing to achieve utopia.

---

<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: [September 3, 2023, 9:10am UTC](https://discourse.julialang.org/t/the-expression-solution/103435/29 "2023-09-03T09:10:10Z")

</div>

I’d pretty strongly disagree with that. They’re really not relevant to solutions to the expression problem because they’re closed by design. There’s nothing you can do with them that can’t be done with relatively simple `if-else` statements. The benefit of sum types is in uniformity, ergonomics and efficiency. Not extensibility or modularity. They’re explicitly non-extensible.

---

<div class="post-metadata">

### Author: ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)
#### Post date: [September 3, 2023, 9:29am UTC](https://discourse.julialang.org/t/the-expression-solution/103435/30 "2023-09-03T09:29:43Z")

</div>

True. And type classes ‘open up’ the sum types, so they themselves are not expanded, but they are still used underneath.

And as you see in the F# example, are there also other ways, to solve that closed nature of sum types.

Although I still prefer the multiple dispatch approach, for its simplicity.  
It seems like one of the more elegant ways, to solve that expression problem.

---

<div class="post-metadata">

### Author: ![mstewart](https://avatars.discourse-cdn.com/v4/letter/m/b5a626/32.png) [@mstewart](https://discourse.julialang.org/u/mstewart)
#### Post date: [September 3, 2023, 11:17am UTC](https://discourse.julialang.org/t/the-expression-solution/103435/31 "2023-09-03T11:17:23Z")

</div>

Most of the things I’ve seen written about the expression problem in the context of Haskell actually use the closed nature of sum types as an illustration of the problem, not its solution. Type classes are usually suggested as the solution, as has already been mentioned here. Otherwise, I think you need to change sum types to something like OCaml’s polymorphic variants to directly address the expression problem. (Or so I think from what I’ve read. I have used Haskell quite a bit, but I don’t have any real experience with OCaml).

---

<div class="post-metadata">

### Author: ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)
#### Post date: [September 3, 2023, 11:25am UTC](https://discourse.julialang.org/t/the-expression-solution/103435/32 "2023-09-03T11:25:26Z")

</div>

OCaml uses higher order modules, in place of type classes.

[Previous page](https://discourse.julialang.org/t/the-expression-solution/103435.md?page=1)
