Simple sum types

There are quite a few julia packages for sum types:

Probably more. For my usecase, I am looking for a sum types package with the following tradeoffs:

  • I don’t need parametric types
  • I don’t need recursion
  • There should be as little performance gotchas as possible. It should be hard to accidentally write slow code with sum types
  • There should be a pattern matching macro that checks that all cases are handled.
  • The package implementation should be simple and easy to maintain.

Are there good options with these specific goals?

2 Likes

Yup, the latest and greatest for most is:

(on GitHub: GitHub - Roger-luo/Moshi.jl: nextgen MLStyle: Generic Algebraic Data Type + Pattern Match)

5 Likes

Thanks, I will add it to the list. It looks like it is much more featureful and complex than what I was looking for.

I really don’t think it is complex at all. It is way less than what SumTypes originally was. And the available features are only as many as you want.

If you still want a simpler approach, albeit with less features and no exhaustive match, I’d go for LightSumTypes.

2 Likes

LightSumTypes looks pretty nice, just missing a match macro.

Part of what makes it so “light” is that you can just use dispatch, i.e.

f(::A) = 1
f(::B) = 2
f(variant(x))

Could probably turn that into a macro pretty easily though. You’d then just use JET.jl to check for completeness by checking for the possibility of method errors.

1 Like

Does dispatch always have good performance or is there a cliff once you have 32 variants say?

I’ve done some light testing previously and it seems to work fine even with very large numbers of variants. E.g. here’s a benchmark on a sum type with 64 variants and the numbers indicate that it’s spending only one clock cycle per application of f:

julia> using LightSumTypes, Random

julia> var_vec = let variants = [Symbol(:A, i) for i ∈ 1:64]
           for (i, var) ∈ enumerate(variants)
               @eval begin
                   struct $var end
                   f(::$var) = $i
               end
           end
           @eval begin
               @sumtype S($(variants...),)
               f(s::S) = f(variant(s))
           end
           shuffle!([S(getproperty(Main, var)()) for var ∈ variants])
       end;
julia> @benchmark sum(f, $var_vec)
BenchmarkTools.Trial: 10000 samples with 990 evaluations.
 Range (min … max):  42.151 ns … 378.326 ns  ┊ GC (min … max): 0.00% … 0.00%
 Time  (median):     43.466 ns               ┊ GC (median):    0.00%
 Time  (mean ± σ):   44.029 ns ±   9.632 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

        ▃█▅                                                     
  ▂▄▂▂▃▆███▇▅▃▃▂▂▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▂▂▂▁▂▂ ▃
  42.2 ns         Histogram: frequency by time         52.3 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.
4 Likes