-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Allow custom types to get narrow Union type with map (like promote_typejoin
for Missing
/Nothing
)
#38241
Comments
There's a lot of cheating with those two (but not really by the compiler): Lines 41 to 70 in a80f903
Here is another example: julia> struct Foo
x::Ref{Union{Nothing, Float64}}
end
julia> Foo(1)
Foo(Base.RefValue{Union{Nothing, Float64}}(1.0))
julia> struct MyMissing end
julia> struct Bar
x::Ref{Union{MyMissing, Float64}}
end
julia> Bar(1)
ERROR: MethodError: Cannot `convert` an object of type
Int64 to an object of type
Union{MyMissing, Float64}
Closest candidates are:
convert(::Type{T}, ::T) where T at essentials.jl:171 |
Nice. |
https://github.com/KristofferC/LazilyInitializedFields.jl/pull/1/files#diff-0abed87289859febd0e9c73389d5bb7fae46aa675acf8f1a468de7a3b9dcf0a1R95-R124 got me most of the way there. I still think there was something that was not perfect but don't really recall it. |
Being extensible wasn't the priority when we implemented this, but maybe it could be made easier and documented. There's also |
This is based on the explicit |
Doesn't this issue remain open to document how to use Or to make it extensible? |
bump |
There's no "cheating" or uncertainty: it's the explicit implementation, and can't be extended, so there's not much to document? |
but just because it can't be extended now doesn't mean that it is impossible for making it extendable in the future. |
I agree with @oxinabox; is there some rewording of this issue that could be reopened? |
Bump :) Can this be reopened or else a brief explanation be added on why this can't/won't be supported? |
FWIW, we're relying on this behaviour as well in our product. @etpinard used this: julia> Base.promote_typejoin(::Type{Blag}, ::Type{T}) where {T} =
isconcretetype(T) || T === Union{} ? Union{T, Blag} : Any
julia> Base.promote_typejoin(::Type{T}, ::Type{Blag}) where {T} =
isconcretetype(T) || T === Union{} ? Union{T, Blag} : Any which works for us as end-users, although it's susceptible to method ambiguities, so I wouldn't use it inside of a library. It's both 1.5 and 1.6-compatible. |
Wouldn't it be possible to allow singleton types to opt into this with a trait? |
I think that would be a good half-solution, but the better (and harder) solution would be to make singletons play nicer without having to ask. |
Why? Or is it just always preferred? |
If it's possible to use a trait, is there a reason not to use |
Mentioned on the #statistics channel in the Slack -- being able to create custom Missing-like structs could be very useful for distinguishing between different kinds of missing data, e.g. data that are missing completely at random vs data that have been censored. |
This could probably be solved by having an |
That's not good, as you can only have one supertype. Also this behavior is not linked on any way to the notion of missing. |
promote_typejoin
for Missing/
Nothing`)
promote_typejoin
for Missing/
Nothing`)promote_typejoin
for Missing
/Nothing
)
Small update, but the special casing of Line 174 in 8181316
So if you for example do: struct MySingleton end
foo(::Nothing) = MySingleton();
foo(x) = x;
xs = [1, 2, nothing, 4]
ys = map(foo, xs)
@show typeof(ys)
@eval Base Base._promote_typesubtract(@nospecialize(a)) = typesplit(a, Union{Nothing, Missing, $MySingleton})
ys = map(foo, xs)
@show typeof(ys) it will show Vector{Any}
Vector{Union{MySingleton, Int64}} |
Speaking with Jameson a bit, a possible solution to this would be to just always go to a |
Yeah, that sounds like a pretty good compromise to me. |
👍 from me too, but it doesn't help with
We're also doing something similar ( |
Are you sure you need to mix |
That's an interesting approach. Our |
Consider this code:
We can see we get a nice array of small unions in the output.
But if I make my own similar singleton type, then the output is a
Array{Any}
.Is there something extra i need to do, or is the compiler cheating for
Missing
andNothing
?The text was updated successfully, but these errors were encountered: