Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an analogue of Haskell's Either type in Julia

Tags:

julia

I want to create an analogue of the Data.Either type from Haskell in Julia. The following works in v0.5:

immutable Either{T, S}
    left :: Nullable{T}
    right :: Nullable{S}
end

either{T, S}(::Type{T}, ::Type{S}, value::T) = Either(Nullable{T}(value), Nullable{S}())
either{T, S}(::Type{T}, ::Type{S}, value::S) = Either(Nullable{T}(), Nullable{S}(value))

a = either(Int64, String, 1)
b = either(Int64, String, "a")

println(a)
println(b)

My question is: is it possible to make the following constructions work:

a = Either{Int64, String}(1)
b = Either{Int64, String}("a")

(this way an additional constructor function is not required).

It seems that there should be enough information to construct the object, but so far I could not persuade the compiler to accept any of the variants I tried; e.g. writing

immutable Either{T, S}
    left :: Nullable{T}
    right :: Nullable{S}

    Either(value::T) = Either(Nullable{T}(value), Nullable{S}())
    Either(value::S) = Either(Nullable{T}(), Nullable{S}(value))
end

results in

ERROR: LoadError: MethodError: no method matching Either{T,S}(::Nullable{Int64}, ::Nullable{String})
like image 719
fjarri Avatar asked Jan 06 '17 04:01

fjarri


1 Answers

It seems that I forgot that the default constructor is called with new. This variant works:

immutable Either{T, S}
    left :: Nullable{T}
    right :: Nullable{S}

    Either(value::T) = new(Nullable{T}(value), Nullable{S}())
    Either(value::S) = new(Nullable{T}(), Nullable{S}(value))
end

a = Either{Int64, String}(1)
b = Either{Int64, String}("a")

println(a)
println(b)

Plus, since the default constructor is not exposed, you can't create an object with two non-null values, so the invariant is enforced automatically.

like image 83
fjarri Avatar answered Oct 22 '22 09:10

fjarri