Why were match types added to scala3 despite method uoverloading fulfilling the same role?

76 Views Asked by At

I was just watching a video by rockthejvm that can be found here. My only issue is that it fails to address if match types can do anything method overloading cannot? Is there anything that match types do better than method overloading? It seems they are just a less extensible version of method overloading.

Any wisdom would be greatly appreciated.

1

There are 1 best solutions below

0
On BEST ANSWER

This example from the documentation:

type LeafElem[X] = X match
  case String => Char
  case Array[t] => LeafElem[t]
  case Iterable[t] => LeafElem[t]
  case AnyVal => X

def leafElem[X](x: X): LeafElem[X] = x match
  case x: String      => x.charAt(0)
  case x: Array[t]    => leafElem(x(9))
  case x: Iterable[t] => leafElem(x.head)
  case x: AnyVal      => x

can't be translated to overloading. The non-recursive cases are easy:

def leafElem(x: String): Char = x.charAt(0)
def leafElem(x: AnyVal): AnyVal = x

but what would you do with arrays? If you write

def leafElem[T](x: Array[T]): ??? = leafElem(x(9))

then:

  1. without match types you can't write the return type (and you have to, because it's an overloaded method);
  2. even if you could, you can't express the constraint "T must be the parameter type of a leafElem overload" required for the body to compile.

Or consider this non-recursive example

type Elem[X] = X match
  case String => Char
  case Array[t] => t
  case Iterable[t] => t

def elem[X](x: X): Elem[X] = x match { /* doesn't really matter */ }

With match types you can write

def mapElems[X](seq: Seq[X]): Seq[Elem[X]] = seq.map(elem(_))

If you had overloaded elem methods for separate cases, mapElems wouldn't compile (and again you couldn't write its return type if it did).