Skip to content

Instantly share code, notes, and snippets.

@soc
Last active December 18, 2015 12:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save soc/5784587 to your computer and use it in GitHub Desktop.
Save soc/5784587 to your computer and use it in GitHub Desktop.
X means "preferred" x means "I could live with that, too"
The Union Type Quiz
===================
0. Please give your typing approach an intuitive name:
User-friendly, backward-compatible union types
1. Please describe the guiding principle of your typing approach in one sentence:
Union types are used for more precise typing, with some special coding for sealed hierarchies.
It is backward compatible with existing code because the inferred union types are always a
subtype of the formerly inferred common supertype (LUB).
The main focus is user-friendliness, reducing the amount of surprising or infinite types the
compiler infers.
2. Should there be predefined implicit widening conversions between numbers?
( ) Yes, even if they are lossy
(x) 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]?
(X) Always
( ) Never
( ) Sometimes: ______________________________
( ) Other: ______________________________
Why?
It doesn't wrap its elements, provides the API of
the common supertype of A and B.
6. Do prefer a nullable type T? to e. g. Option[T]?
( ) Always
(X) Never
( ) Sometimes: ______________________________
( ) Other: ______________________________
Why?
Option might not always be the right abstraction.
7. Explain why your answer to A|B vs. Either[A, B] is consistent and intuitive with your answer to T? vs. Option[T]:
Union types are more fundamental than nullable types.
Compared to nullable types, union types provide already a useful API without
wrapping it into a different type like Option.
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
( ) Other: ______________________________
9. Does your answer change if
- trait T is sealed?
(X) Yes, because: The common supertype should be inferred.
( ) No, because: __________________________________________________
- A and/or B are classes?
( ) Yes, because: __________________________________________________
(X) No, because: __________________________________________________
- A/B/T are type constructors?
( ) Yes, because: __________________________________________________
( ) No, because: __________________________________________________
(X) No idea.
10. What should be the inferred type of
if (true) Some(1) else None?
(X) Option[Int]
( ) Some[Int]|None
( ) Other: ______________________________
11. What should be the inferred type of
if (true) Nil else List(1).asInstanceOf[::[Int]]?
(X) List[Int]
( ) Nil|::[Int]
( ) Other: ______________________________
12. When should a nominal type be preferred to a more precise union type?
( ) Always
( ) Never
(X) Only if the element types enumerate all subclasses/subobjects of a sealed supertype
( ) Other: ______________________________
13. When should a more precise structural type be preferred to a union type?
(x) Always
( ) Never
(X) 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?
No idea. Is there any interesting interaction?
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?
(X) Yes
( ) 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?
(X) Yes
( ) No
( ) Other: ______________________________
18. Will your choice from above break existing, valid code?
( ) Yes
( ) Yes, but it doesn't matter because: ______________________________
(X) No, because: Inferring union types will create only more precise types than before, never less precise code.
( ) Maybe?
19. Describe how null will work with union types:
Have not thought about whether there is anything special to consider.
20. Will your design make a difference whether a type has been inferred and has been specified explicitly?
No.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment