Skip to content

Instantly share code, notes, and snippets.

@shelby3
Forked from soc/The Union Type Quiz
Last active December 23, 2015 13:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shelby3/6639849 to your computer and use it in GitHub Desktop.
Save shelby3/6639849 to your computer and use it in GitHub Desktop.
The Union Type Quiz
===================
0. Please give your typing approach an intuitive name:
Consistent, Unified Subsumption
1. Please describe the guiding principle of your typing approach in one sentence:
Union is chosen over widening only when all types participating in the subsumption would be widened[1].
[1] https://groups.google.com/d/msg/scala-language/B6f-iubR9Mk/XFjQFsiQbpYJ
2. Should there be predefined implicit widening conversions between numbers?
( ) Yes, even if they are lossy
( ) Yes, but only non-lossy ones
(X) No
( ) Other: ______________________________
3. What should be the inferred type of the expression
List(1, 1.0)?
( ) List[Double]
( ) List[AnyVal]
(X) List[Int|Double]
( ) Other: ______________________________
4. What should be the inferred type of the expression
List(1: java.lang.Integer, 1.0: java.lang.Double)?
( ) List[Number with Comparable[_ >: Double with Integer <: Number with Comparable[_ >: Double with Integer <: Number ...]]]
(X) List[java.lang.Integer|java.lang.Double]
( ) Other: ______________________________
5. Do you prefer a union type A|B to Either[A, B]?
( ) Always
( ) Never
( ) Sometimes: ______________________________
(X) Other: Need both.
6. Do prefer a nullable type T? to e. g. Option[T]?
( ) Always
( ) Never
( ) Sometimes: ______________________________
(X) Other: For GC and runtime performance yes, but it must have same semantics as Option[T]
in that it was be logically unboxed before use, c.f. the plans to make extractors nearly as
performant as case classes.
8. Given the following declarations ...
trait T
object A extends T
object B extends T
... what should be the inferred type of
if (true) A else B
( ) T
(X) A|B, to get T then use a cast. Note if this expression is the result type of a function
declared to return T, then the subsumption is to T as the result type, per my rule in question 1.
( ) Other: ______________________________
9. Does your answer change if
- trait T is sealed?
( ) Yes, because: __________________________________________________
(X) No, because: of my rule in question 1
- A and/or B are classes?
( ) Yes, because: __________________________________________________
(X) No, because: of my rule in question 1
- A/B/T are type constructors?
( ) Yes, because: __________________________________________________
(X) No, because: of my rule in question 1
10. What should be the inferred type of
if (true) Some(1) else None?
( ) Option[Int]
(X) Some[Int]|None, ditto question 8. Note that once we have unions, it would make sense to deprecate
Option and instead write the Option[Int] type as Some[Int]|None. Thus casts won't be necessary.
( ) Other: ______________________________
11. What should be the inferred type of
if (true) Nil else List(1).asInstanceOf[::[Int]]?
( ) List[Int]
(X) Nil|::[Int]
( ) Other: ______________________________
12. When should a nominal type be preferred to a more precise union type?
( ) Always
( ) Never
( ) Only if the element types enumerate all subclasses/subobjects of a sealed supertype
(X) Other: my rule in question 1
13. When should a more precise structural type be preferred to a union type?
( ) Always
(X) Never, except where my rule in question 1 allows it.
( ) Only if the structural type is specified explicitly
( ) Other: ______________________________
14. Given the following declarations ...
trait T { def foo: Int }
class A extends T { def foo: Int = ???; def bar: Int = ??? }
class B extends T { def foo: Int = ???; def bar: Int = ???; def bippy: Int = ??? }
... which members are allowed to be called on an instance aOrB of type A|B?
[X] aOrB.toString
[X] aOrB.foo
[ ] aOrB.bar
[ ] aOrB.bippy
15. How will inference of union types interact with structural types?
Structural types subsume to any nominal (i.e. named) types they are conjuncted `with`,
else to AnyRef.
We can't extract unnamed types from the union in a pattern match. Unions of nominal types
is ambitious enough for current Scala type system. There is talk about a future Scala type
system that would be more ambitious.
16. Given the following definitions ...
val x: AnyRef { def foo: Int } = null
val y: AnyRef { def foo: Int } = null
... should it be allowed to call xOrY.foo?
( ) Yes
(X) No
( ) Other: ______________________________
17. Given the following definitions ...
val x = new AnyRef { def foo: Int = 23}
val y = new AnyRef { def foo: Int = 42}
... should it be allowed to call xOrY.foo?
( ) Yes
(X) No
( ) Other: ______________________________
18. Will your design break existing, valid code?
( ) Yes
(X) Yes, but it doesn't matter because: as far as I can see, it is the only way we
can have a consistent, unified rule for subsumption. Unfortunate it wasn't done earlier,
yet hopefully there orders-of-magnitude more Scala code to be written especially if we
closing gaping holes such as the lack of unions.
( ) No, because: ______________________________
( ) Maybe?
19. Describe how null will work with union types:
A union may have a null value.
20. Will your design make a difference whether a type has been inferred and has been specified explicitly?
No, always adhere to the rule I provided in question 1.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment