|
1 | | -abstract type Either{L, R} end |
2 | | - |
3 | | -# variable naming taken from Base.Some |
4 | | -struct Left{L, R} <: Either{L, R} |
| 1 | +struct Left{L} |
5 | 2 | value::L |
6 | 3 | end |
7 | | -Left{L}(x::L) where {L} = Left{L, Any}(x) |
8 | | -Left(x::L) where {L} = Left{L, Any}(x) |
9 | | -# TODO the typecast conflict with nested applications |
10 | | -# Left{L, R}(x::Left{L}) where {L, R} = Left{L, R}(x.value) |
11 | | -# Left{R}(x::Left{L}) where {L, R} = Left{L, R}(x.value) |
12 | 4 |
|
13 | | -struct Right{L, R} <: Either{L, R} |
| 5 | +struct Right{R} |
14 | 6 | value::R |
15 | 7 | end |
16 | | -Right{L}(x::R) where {L, R} = Right{L, R}(x) |
17 | | -Right(x::R) where {R} = Right{Any, R}(x) |
18 | | -# TODO the typecast conflict with nested applications |
19 | | -# Right{L}(x::Right{<:Any, R}) where {L, R} = Right{L, R}(x.value) |
20 | | - |
21 | | -# TODO the typecast conflict with nested applications |
22 | | -# Either{L, R}(x::Left{L}) where {L, R} = Left{L, R}(x.value) |
23 | | -# Either{L, R}(x::Right{<:Any, R}) where {L, R} = Right{L, R}(x.value) |
24 | | -Either{L, R}(x::L) where {L, R} = Left{L, R}(x) |
25 | | -Either{L, R}(x::R) where {L, R} = Right{L, R}(x) |
26 | | -Either{L, R}(x::L) where {L, R} = Left{L, R}(x) |
27 | | -Either{L, R}(x::R) where {L, R} = Right{L, R}(x) |
28 | 8 |
|
29 | | -Either{L}(x::R) where {L, R} = Right{L, R}(x) |
30 | | -Either{L}(x::L) where {L} = Left{L, Any}(x) |
| 9 | +const Either{L, R} = Union{Left{L}, Right{R}} |
| 10 | +Either{L, R}(x::L) where {L, R} = Left(x) |
| 11 | +Either{L, R}(x::R) where {L, R} = Right(x) |
| 12 | +Either{L}(x::R) where {L, R} = Right(x) |
| 13 | +Either{L}(x::L) where {L} = Left(x) |
| 14 | + |
| 15 | + |
| 16 | +# conversions/ promotions |
| 17 | + |
| 18 | +# typejoin Left & Left |
| 19 | +Base.typejoin(::Type{Left{L}}, ::Type{Left{L}}) where L = Left{L} |
| 20 | +Base.typejoin(::Type{<:Left}, ::Type{<:Left}) = Left |
| 21 | +# typejoin Right & Right |
| 22 | +Base.typejoin(::Type{Right{R}}, ::Type{Right{R}}) where R = Right{R} |
| 23 | +Base.typejoin(::Type{<:Right}, ::Type{<:Right}) = Right |
| 24 | +# typejoin Left & Right |
| 25 | +Base.typejoin(::Type{Left{L}}, ::Type{Right{R}}) where {L, R} = Either{L, R} |
| 26 | +Base.typejoin(::Type{Right{R}}, ::Type{Left{L}}) where {L, R} = Either{L, R} |
| 27 | +# typejoin Left & Either |
| 28 | +Base.typejoin(::Type{Left{L}}, ::Type{<:Either{L, R}}) where {L, R} = Either{L, R} |
| 29 | +Base.typejoin(::Type{<:Either{L, R}}, ::Type{Left{L}}) where {L, R} = Either{L, R} |
| 30 | +Base.typejoin(::Type{<:Left}, ::Type{<:Either{<:Any, R}}) where {R} = Either{<:Any, R} |
| 31 | +Base.typejoin(::Type{<:Either{<:Any, R}}, ::Type{<:Left}) where {R} = Either{<:Any, R} |
| 32 | +# typejoin Right & Either |
| 33 | +Base.typejoin(::Type{Right{R}}, ::Type{<:Either{L, R}}) where {L, R} = Either{L, R} |
| 34 | +Base.typejoin(::Type{<:Either{L, R}}, ::Type{Right{R}}) where {L, R} = Either{L, R} |
| 35 | +Base.typejoin(::Type{<:Right}, ::Type{<:Either{L}}) where {L} = Either{L} |
| 36 | +Base.typejoin(::Type{<:Either{L}}, ::Type{<:Right}) where {L} = Either{L} |
| 37 | +# typejoin Either & Either |
| 38 | +Base.typejoin(::Type{<:Either{L, R}}, ::Type{<:Either{L, R}}) where {L, R} = Either{L, R} |
| 39 | +Base.typejoin(::Type{<:Either{L}}, ::Type{<:Either{L}}) where {L} = Either{L} |
| 40 | +Base.typejoin(::Type{<:Either{<:Any, R}}, ::Type{<:Either{<:Any, R}}) where {R} = Either{<:Any, R} |
| 41 | +Base.typejoin(::Type{<:Either}, ::Type{<:Either}) = Either |
| 42 | + |
| 43 | +# Left/Right are covariate |
| 44 | +Base.convert(::Type{Right{T}}, x::Right{S}) where {S, T} = Right(Base.convert(T, x.value)) |
| 45 | +Base.convert(::Type{Left{T}}, x::Left{S}) where {S, T} = Left(Base.convert(T, x.value)) |
| 46 | +Base.convert(::Type{Either{L, R2}}, x::Right{R}) where {L, R, R2} = Right(Base.convert(R2, x.value)) |
| 47 | +Base.convert(::Type{Either{L2, R}}, x::Left{L}) where {L, L2, R} = Left(Base.convert(L2, x.value)) |
| 48 | +promote_rule(::Type{Left{T}}, ::Type{Left{S}}) where {T, S<:T} = Left{T} |
| 49 | +promote_rule(::Type{Right{T}}, ::Type{Right{S}}) where {T, S<:T} = Right{T} |
31 | 50 |
|
32 | 51 |
|
33 | 52 | # == controversy https://github.com/JuliaLang/julia/issues/4648 |
34 | | -Base.:(==)(a::Either, b::Either) = either_compare(a, b) |
35 | | -either_compare(a::Right, b::Right) = a.value == b.value |
36 | | -either_compare(a::Left, b::Right) = false |
37 | | -either_compare(a::Right, b::Left) = false |
38 | | -either_compare(a::Left, b::Left) = a.value == b.value |
| 53 | +Base.:(==)(a::Right, b::Right) = a.value == b.value |
| 54 | +Base.:(==)(a::Left, b::Right) = false |
| 55 | +Base.:(==)(a::Right, b::Left) = false |
| 56 | +Base.:(==)(a::Left, b::Left) = a.value == b.value |
39 | 57 |
|
40 | 58 | # TypeClasses.unionall_implementationdetails(::Type{<:Either{L, R}}) where {L, R} = Either{L, R} |
41 | 59 | # Traits.leaftypes(::Type{Either}) = [Either{newtype(), newtype(), Left}, Either{newtype(), newtype(), Right}] |
42 | 60 | # Traits.leaftypes(::Type{Either{T}}) where T = [Either{T, newtype(), Left}, Either{T, newtype(), Right}] |
43 | 61 |
|
44 | 62 |
|
45 | | -function either(left_false::L, comparison::Bool, right_true::R) where {L, R} |
46 | | - comparison ? Right{L, R}(right_true) : Left{L, R}(left_false) |
| 63 | +function either(left_false, comparison::Bool, right_true) |
| 64 | + comparison ? Right(right_true) : Left(left_false) |
47 | 65 | end |
48 | 66 |
|
49 | | -flip(x::Left{L, R}) where {L, R} = Right{R, L}(x.value) |
50 | | -flip(x::Right{L, R}) where {L, R} = Left{R, L}(x.value) |
| 67 | +flip_left_right(x::Left) = Right(x.value) |
| 68 | +flip_left_right(x::Right) = Left(x.value) |
51 | 69 |
|
52 | | -isleft(e::Either) = either_isleft(e) |
53 | | -either_isleft(e::Left) = true |
54 | | -either_isleft(e::Right) = false |
| 70 | +isleft(e::Left) = true |
| 71 | +isleft(e::Right) = false |
55 | 72 |
|
56 | | -isright(e::Either) = either_isright(e) |
57 | | -either_isright(e::Left) = false |
58 | | -either_isright(e::Right) = true |
| 73 | +isright(e::Left) = false |
| 74 | +isright(e::Right) = true |
59 | 75 |
|
60 | | -getleft(e::Either) = either_getleft(e) |
61 | | -either_getleft(e::Left) = e.value |
62 | | -either_getleft(e::Right) = nothing |
| 76 | +getleft(e::Left) = e.value |
| 77 | +getleft(e::Right) = nothing |
63 | 78 |
|
64 | | -getright(e::Either) = either_getright(e) |
65 | | -either_getright(e::Left) = nothing |
66 | | -either_getright(e::Right) = e.value |
| 79 | +getright(e::Left) = nothing |
| 80 | +getright(e::Right) = e.value |
67 | 81 |
|
68 | | -getleftOption(e::Either) = either_getleftOption(e) |
69 | | -either_getleftOption(e::Left{L, R}) where {L, R} = Some{L}(e.value) |
70 | | -either_getleftOption(e::Right{L, R}) where {L, R} = None{L}() |
| 82 | +getleftOption(e::Left{L}) where {L} = Some{L}(e.value) |
| 83 | +getleftOption(e::Right) = nothing |
71 | 84 |
|
72 | | -getrightOption(e::Either) = either_getrightOption(e) |
73 | | -either_getrightOption(e::Left{L, R}) where {L, R} = None{R}() |
74 | | -either_getrightOption(e::Right{L, R}) where {L, R} = Some{R}(e.value) |
| 85 | +getrightOption(e::Left) = nothing |
| 86 | +getrightOption(e::Right{R}) where {R} = Some{R}(e.value) |
75 | 87 |
|
76 | 88 | Base.get(e::Either) = getright(e) |
77 | 89 | getOption(e::Either) = getrightOption(e) |
78 | 90 |
|
79 | 91 | Base.eltype(::Type{<:Either{L, R}}) where {L, R} = R |
| 92 | +Base.eltype(::Type{<:Left{L}}) where L = Any # we have to specify this clause as otherwise we get ERROR: UndefVarError: R not defined |
80 | 93 | Base.eltype(::Type{<:Either}) = Any |
81 | 94 |
|
82 | | -Base.iterate(e::Either, state...) = either_iterate(e, state...) |
83 | | -either_iterate(e::Right) = e.value, nothing |
84 | | -either_iterate(e::Right, state) = state |
85 | | -either_iterate(e::Left) = nothing |
86 | | - |
87 | | -Base.foreach(f, x::Either) = either_foreach(f, x) |
88 | | -either_foreach(f, x::Right) = f(x.value); nothing |
89 | | -either_foreach(f, x::Left) = nothing |
90 | | - |
91 | | -Base.map(f, x::Either) = either_map(f, x) |
92 | | -either_map(f, x::Right{L}) where {L} = Right{L}(f(x.value)) |
93 | | -function either_map(f, x::Left{L, R}) where {L, R} |
94 | | - _R2 = Out(f, R) |
95 | | - R2 = _R2 === NotApplicable ? Any : _R2 |
96 | | - Left{L, R2}(x.value) |
97 | | -end |
| 95 | +Base.iterate(e::Right) = e.value, nothing |
| 96 | +Base.iterate(e::Right, state) = state |
| 97 | +Base.iterate(e::Left) = nothing |
| 98 | + |
| 99 | +Base.foreach(f, x::Right) = f(x.value); nothing |
| 100 | +Base.foreach(f, x::Left) = nothing |
| 101 | + |
| 102 | +Base.map(f, x::Right) = Right(f(x.value)) |
| 103 | +Base.map(f, x::Left) = x |
98 | 104 |
|
99 | | -Iterators.flatten(e::Either) = either_flatten(e) |
100 | | -either_flatten(x::Right) = convert(Either, x.value) |
101 | | -either_flatten(x::Left) = x |
102 | | -either_flatten(x::Left{L, E}) where {L, R, E <: Either{L, R}} = Left{L, R}(x.value) # just to have better type support |
| 105 | +Iterators.flatten(x::Right) = convert(Either, x.value) |
| 106 | +Iterators.flatten(x::Left) = x |
0 commit comments