Match Types in Dotty

Reading Time: 2 minutes

As we already know that Dotty is the new Scala version and will obviously be more stronger and powerful then Scala 2.
In Scala-2, pattern matching is only applicable to the objects and not on the types. But with the new Scala compiler i.e Dotty, it is possible to apply matching on Types also.

For example,

type Container[C] = C match {
  case String => Char
  case Array[Int] => Int
  case Iterable[Int] => Int
}

The Container is a type which gets reduce to further corresponding types as under –

Container[String] -> Char
Container[Array[Int]]-> Int, and
Container[List[Double]] -> Double

Match types are a very powerful and also provides support for recursive definition. See the example below –

import scala.compiletime.ops.int.%

type HCF[A <: Int, B <: Int] <: Int = B match {
  case 0 => A
  case _ => HCF[B, A % B]
}

Here the HCF type is of a Singleton Type. Singleton Type are the types which are instantiated with exactly one value. So you have a HCF type and then create its object as –

val hcf: HCF[10, 20] = 10

Here we have defined a value which carries the highest common factor of two numbers 10 & 20.
But if you try to change the value to something else, you should see the compilation error.
The below statement will lead to compilation error-

val hcf: HCF[10, 20] = 11

// you should see error..

val hcf: HCF[10, 20] =    11
  |                       ^^
  |                       Found:    (11 : Int)
  |                       Required: (10 : Int)

This is because value hcf is of type 10 which is a singleton type and thus exactly have one value.

Match types can also detect infinite loop if it is defined as an endless recursion. The compiler internally detects it by stack overflows. If there is a stack overflow, it will be taken as a compile-time error.

The example is available on the GitHub.

How compiler reduces the Match Type:

Semantically match type reduction is same as it is done in Match expressions.

S match {P1 => T1 ... Pn => Tn}

which can be further reduced to something as (similar with the pattern matching done in Scala 2):

s: S match {_: P1 => T1 ... _: Pn => Tn}

And it gets reduced to Ti only when S is of type Pi.

The algorithm which compiler implements for match type reduction is as:

For every Pi

  • if S is lower bound of Pi i.e. S <: Pi, then reduce to Pi.
  • else, check that no value s of type S should be of type Pi i.e S and Pi are disjoint.
  • And if the check fails, then follow the same procedure for (Pi+1).

References:


Knoldus-blog-footer-image

Written by 

Harshit Daga is a Sr. Software Consultant having experience of more than 4 years. He is passionate about Scala development and has worked on the complete range of Scala Ecosystem. He is a quick learner & curious to learn new technologies. He is responsible and a good team player. He has a good understanding of building a reactive application and has worked on various Lightbend technologies like Scala, Akka, Play framework, Lagom, etc.