Scala 3 aka dotty comes with a lot of new types. Union, Intersection , Opaque etc. Let’s understand union and intersection types in detail.
A union type
A | B represents a type that has values of type
B at a given time. A pattern match must be performed at the point of usage to extract the exact type.
This would not have been possible in Scala 2. We would have to create a super type for our types and then create the method with the super type.
Rules for Union types
- Union types are commutative i.e
A | Bis same as
B | A.
Bare sub types of
A | Bfor all values of
- Co- Variance rules for Union types : Given a co-variant type
C[A] | C[B] <: C[A | B]
Basically we can pass a
List[Int] and a
List[String] to a method expecting a
List[Int|String]. This makes
C[B] a sub type of
Also we can pass
List[String]|List[Int] type where a
List[String|Int] is expected. This makes
C[A] | C[B] a sub type of
C[A|B]. However the reverse is not possible as seen in line 24.
- Contra-variance rules for Union types : Given a contra variant type C then
C[A | B] <: C[A]and
C[A | B] <: C[B]
Here, we see that we could pass a
Printer[String|Int] where a
Printer[Int] was required.
A intersection type
A & B represents a type that has values of type
B at the same time.
At line 8 we are able to use both methods from intersection type i.e
monoid contains the functionality of both Semigroup and Indentity types. The intersection type will also act as a type restriction, so we need to mix in both traits if we are to use this method properly.
Rules for Intersection types
- Intersection types are commutative i.e
A & Bis same as
B & A.
- Given any types
A & Bis a sub type for both
- Co- Variance rules for Intersection types : Given a co-variant type
C[A & B] <: C[A] & C[B]
Here, we see that we can provide an
Option[TwitterPost & InstagramPost]when we need a
Option[TwitterPost] or a
Option[InstagramPost]. This also leads us to the fact that when we need an
Option[TwitterPost] & Option[InstagramPost] we can provide a
Option[TwitterPost & InstagramPost] .
- Given a contra-variant type
C[A |B]is a sub type of
C[A] & C[B]
What happens here is that a
Printer instance which knows how to print
Int|String can be passed when we need a
Printer[Int] & Printer[String]. This is exactly what is done is line 15.
- what happens the two intersected types share a method signature except the returned types?
Dancer types have a method called
share with the same signature but different return types. An intersection type of these two upon calling the
share method must return both an
InstagramPost and a
TwitterPost. The only type that can do that is an intersection i.e
TwitterPost & InstagramPost.
We explored Union and Intersection types in Scala 3 and checked how these types work with variance rules in Scala. Checkout the official dotty docs for further reading