-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Some functions could perform type intersection #2404
Comments
Intersection types are a nice idea. Some days ago @bcardiff suggested to me that # We want something that's an IO, but we also want
# T as a free variable to get the real type
def foo(x : T & IO)
# do something with T
end Using |
Fair enough about |
I would love to see type intersection too. 👍 I can only imagine how useful it will be.
|
Wish to support intersection types. |
The intersection defined this way isn't commutative yet, not even up to equivalent types. Some examples: # covariant Tuple instances
typeof(Intersect({Int32}, {Int32 | Char}).get) # => Tuple(Int32)
typeof(Intersect({Int32 | Char}, {Int32}).get) # => NoReturn
# generic module instances
typeof(Intersect(Indexable(Int32), Enumerable(Int32)).get) # => Indexable(Int32)
typeof(Intersect(Enumerable(Int32), Indexable(Int32)).get) # => NoReturn
# metaclasses between module and including class
typeof(Intersect(File.class, IO.class).get) # => Class
typeof(Intersect(IO.class, File.class).get) # => NoReturn
# metaclasses between superclass and subclass
typeof(Intersect(File.class, IO::FileDescriptor.class).get) # => Class
typeof(Intersect(IO::FileDescriptor.class, File.class).get) # => NoReturn
# nil and void
typeof(Intersect(Nil, Void).get) # => Nil
typeof(Intersect(Void, Nil).get) # => NoReturn If c = a.filter_by(b)
d = b.filter_by(a)
if c && d
c.implements?(d) && d.implements?(c) # C <= D && C >= D
else
c.nil? && d.nil? # both filtered types are NoReturn
end Doing so would also impact flow typing; for example, this might be possible in the future: x = {1 || 'a'}
if x.is_a?({Int32})
typeof(x) # => Tuple(Int32)
else
typeof(x) # => Tuple(Char)
end |
Defining def foo(x : (A & B) | C); end
def foo(x : (A | C) & (B | C)); end
def bar(x : (A | B) & C); end
def bar(x : (A & C) | (B & C)); end It would be good if distributivity holds for any AST node, but I haven't investigated that far yet. Irreducible intersection types are even harder to implement, because if those types are equivalent then it might be preferable to always normalize them to CNFs or DNFs (not doing so would create a situation similar to |
Set
's&
, as an example, is such thatis
which is the type of the LHS, but surely it should really be
This is possible to implement as
The
typeof(Intersect(T, U).get())
stuff isn't the most obvious (I'd much ratherT & U
), but other than that the code works great.Would this be useful?
The text was updated successfully, but these errors were encountered: