When defining sum types inside modules, arguably it would be desirable to be able to use the module prefix in order to make it clear where they are coming from. However, this currently does not seem to work:
```julia
julia> module MySumTypes
using SumTypes
@sum_type MySumType begin
Variant1
Variant2
end
end
Main.MySumTypes
julia> using .MySumTypes, SumTypes
julia> a = MySumTypes.Variant1
Variant1::MySumType
julia> @cases a begin
Variant1 => 1
Variant2 => 2
end
1
julia> @cases a begin
MySumTypes.Variant1 => 1
MySumTypes.Variant2 => 2
end
ERROR: LoadError: Invalid variant MySumTypes.Variant1
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] (::SumTypes.var"#69#72"{Expr, Base.RefValue{Any}, Vector{Any}})(::Tuple{Int64, Expr})
@ SumTypes ~/.julia/packages/SumTypes/aO6qd/src/cases.jl:69
[3] foreach(f::SumTypes.var"#69#72"{Expr, Base.RefValue{Any}, Vector{Any}}, itr::Base.Iterators.Enumerate{Vector{Any}})
@ Base ./abstractarray.jl:3187
[4] _cases(to_match::Symbol, block::Expr)
@ SumTypes ~/.julia/packages/SumTypes/aO6qd/src/cases.jl:35
[5] var"@cases"(__source__::LineNumberNode, __module__::Module, to_match::Any, block::Any)
@ SumTypes ~/.julia/packages/SumTypes/aO6qd/src/cases.jl:22
in expression starting at REPL[29]:1
```
The left hand side of the `=>` in a `@cases` block is **always** the symbols associated with `a`. Namespacing them like this is actually unnecessary.
When you write
```julia
@cases a begin
Variant1 => 1
Variant2 => 2
end
```
here's the macroexpansion:
```julia
julia> @macroexpand1 @cases a begin
Variant1 => 1
Variant2 => 2
end
quote
#= /home/mason/Dropbox/Julia/SumTypes/src/cases.jl:115 =#
let var"##data#264" = a
#= /home/mason/Dropbox/Julia/SumTypes/src/cases.jl:116 =#
var"##Typ#268" = (typeof)(var"##data#264")
#= /home/mason/Dropbox/Julia/SumTypes/src/cases.jl:117 =#
(SumTypes.check_sum_type)(var"##Typ#268")
#= /home/mason/Dropbox/Julia/SumTypes/src/cases.jl:118 =#
(SumTypes.assert_exhaustive)(Val{(SumTypes.tags)(var"##Typ#268")}, Val{(:Variant1, :Variant2)})
#= /home/mason/Dropbox/Julia/SumTypes/src/cases.jl:119 =#
var"##unwrapped#270" = (SumTypes.unwrap)(var"##data#264")
#= /home/mason/Dropbox/Julia/SumTypes/src/cases.jl:120 =#
if var"##unwrapped#270" isa (SumTypes.Variant){:Variant1}
#= REPL[13]:2 =#
nothing
1
elseif var"##unwrapped#270" isa (SumTypes.Variant){:Variant2}
#= REPL[13]:3 =#
nothing
2
end
end
end
```
or a bit more readable:
```julia
julia> prettify(ans)
:(let fly = a
penguin = typeof(fly)
check_sum_type(penguin)
assert_exhaustive(Val{tags(penguin)}, Val{(:Variant1, :Variant2)})
locust = unwrap(fly)
if locust isa (SumTypes.Variant){:Variant1}
nothing
1
elseif locust isa (SumTypes.Variant){:Variant2}
nothing
2
end
end)
```
The point here is that it is only ever checking that the type tag associated with the first argument is `:Variant1` or `:Variant2`, it's not checking the object itself.
This system *cannot* get confused about namespacing because the lhs is always the one associated with the object you apply `@cases` to.
Thanks, the point about the internal consistency is well taken. My point was more about human readability. If neither the name of the sum type nor the module appear in the `@cases` expression, it is somewhat hard to figure out what is happening and where one should look for the definitions. I think a work-around could be that one only uses `@cases` inside a function that is specialized to the sum type with an explicit type annotation.
> If neither the name of the sum type nor the module appear in the `@cases` expression, it is somewhat hard to figure out what is happening and where one should look for the definitions.
Yeah, this is definitely true, but I see it as directly analogous to `getproperty`, i.e. it's the same problem as when you write `x.prop` without writing out what the type of `x` is or where it came from.
> I think a work-around could be that one only uses `@cases` inside a function that is specialized to the sum type with an explicit type annotation.
Yeah, I think that's generally a good idea when working with `@cases`, because using it is only valid if you list every single one of the valid variants anyways, so there's not really any such thing as a "generic" function that applies `@cases`.