Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using parametric struct and only defining the top level type makes it errors out #51

Open
minecraft2048 opened this issue Aug 14, 2023 · 1 comment

Comments

@minecraft2048
Copy link

I'm trying to use SumTypes to replicate Rust Result type, and I expected the Result type to be able to carry all types. Here's the example code:

using SumTypes

#Rust like result type
@sum_type Result{A, B} begin
    Ok{A}(::A)
    Err{B}(::B)
end

#Some default errors
struct SequenceError{T}
    prev::T
    cur::T
end

struct Good 
    good::Int
end


function test(a) :: Result{Good, SequenceError}
    if a
        return Ok(Good(1))
    else
        return Err(SequenceError(1,1))
    end
end

Somehow if my test function tries to return SequenceError it errors out with cannot convert error:

julia> test(true)
Ok(Good(1))::Result{Good, SequenceError}

julia> test(false)
ERROR: MethodError: Cannot `convert` an object of type 
  Result{Uninit,SequenceError{Int64}} to an object of type 
  Result{Good,SequenceError}

Closest candidates are:
  convert(::Type{<:Result{A, B}}, ::Result{Uninit, B}) where {A, B}
   @ Main ~/.julia/packages/SumTypes/Mrn3L/src/sum_type.jl:197
  convert(::Type{T}, ::T) where T
   @ Base Base.jl:84
  convert(::Type{Result{A, B}}, ::Result{Uninit, B}) where {A, B}
   @ Main ~/.julia/packages/SumTypes/Mrn3L/src/sum_type.jl:196
  ...

Stacktrace:
 [1] test(a::Bool)
   @ Main ~/workdir/nanoavionics/result.jl:24
 [2] top-level scope
   @ REPL[59]:1

But if I fully specify the type then it works:

julia> function test2(a) :: Result{Good, SequenceError{Int}}
           if a
               return Ok(Good(1))
           else
               return Err(SequenceError(1,1))
           end
       end
test2 (generic function with 1 method)

julia> test2(true)
Ok(Good(1))::Result{Good, SequenceError{Int64}}

julia> test2(false)
Err(SequenceError{Int64}(1, 1))::Result{Good, SequenceError{Int64}}

This is maybe #44, but I'm not that familiar with Julia type system yet

@MasonProtter
Copy link
Owner

MasonProtter commented Sep 1, 2023

Hey sorry for the late reply @minecraft2048, I've been quite busy lately. Yeah, the problem here is that Julia's type system is invariant, not covariant (see this section of the docs: https://docs.julialang.org/en/v1/manual/types/#man-parametric-composite-types). The best I could do here I think is make it work with you writing :: Result{Good, <:SequenceError}. I'll see what I can do to support that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants