MasonProtter / SumTypes.jl

An implementation of sum types in Julia
MIT License
104 stars 8 forks source link

mutable sum types? #57

Closed Tortar closed 9 months ago

Tortar commented 9 months ago

I'd like to use sum types for a package, but I would need mutable sum types, is it possible to support them?

For now I see that it is already possible with some Base.RefValue wrapping but I'm not sure this is the correct approach e.g.

julia> @sum_type S begin
           A(x::Base.RefValue{Int}, y::Base.RefValue{Int})
           B(x::Base.RefValue{Int}, z::Base.RefValue{Float64})
       end

julia> s = A(Ref(0), Ref(0))
A(Base.RefValue{Int64}(0), Base.RefValue{Int64}(0))::S

julia> s.data.data[1][] = 3
3

julia> s
A(Base.RefValue{Int64}(3), Base.RefValue{Int64}(0))::S

but I'm not sure neither if this is optimal (is this as fast as mutable structs?) nor if it safe since I'm using internal fields to modify data. I wonder if maybe a more "integrated" solution is possible.

MasonProtter commented 9 months ago

Hi @Tortar, yes the correct way to do this would be to wrap the contents in a RefValue (or whatever other type of mutable struct you like).

You should definitely not be doing s.data.data[1][] = 3 though, that's bad.

Instead, you should do something like

s = A(Ref(0), Ref(0))
@cases s begin
    A(x, _) => x[] = 3
    B(x, _) => x[] = 3
end
Tortar commented 9 months ago

thanks for the prompt responses @MasonProtter, what I'd like to ask you is if you think that creating an interface in another package which mimics the working of structs, mutable structs would make sense (and would be possible) in your opinion? Because for example I'm thinking to use SumTypes for some heterogeneous data containers (multi-agent systems) in Agents.jl but I need a syntax equivalent to that of mutable structs to expose to users

Tortar commented 9 months ago

for example it seems maybe possible to wrap the cases macro in getproperty/setproperty

MasonProtter commented 9 months ago

I guess it would be possible to make a Sum Type appear like a regular struct for the purposes of a user-facing interface, but how to do it would be mostly up to you and would depend on your use-case. I don't really have enough information to give advice on this