HOME | EDIT | RSS | INDEX | ABOUT | GITHUB

# Generalized Algebraic Datatypes in Scala 3

I'm recently migrating some libs and projects to Scala 3, I guess it would be very helpful to me or anyone interested to learn some new functional programming features that Scala 3 is bringing to us.

Source code 👉 https://github.com/jcouyang/meow

ADTAlgebraic Datatypes is something that has multiple constructors return single type:

```enum List[+A]:
case Nil
case Cons(head: A, tail: List[A])
```

Here both `Nil` and `Cons` can create a value of type `List[A]`.

This is great improvement from Scala 2, since defining an ADT is much easier than before:

``````sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[A](head: A, tail: List[A]) extends List[A]
``````

But actually the way Scala 2 using is GADTGeneralized Algebraic Datatypes.

We can also do GADT using `enum`, for instance to define a `SafeList`:

``````1: enum Size:
2:   case Empty
3:   case NonEmpty
4:
5: enum SafeList[+A, +S <: Size]:
6:   case Nil extends SafeList[Nothing, Size.Empty.type] // <-
7:   case Cons(head: A, tail: SafeList[A, Size]) extends SafeList[A, Size.NonEmpty.type]
``````

What GATD provides fine control of type, i.e. line 6 no longer returns `List[Nothing]`, we can let it return something else `SafeList[Nothing, Size.Empty.type]`

Same way we can make `Cons` return `SafeList[A, Size.NonEmpty.type]`, which tag it as `NonEmpty` at type level.

So we can simply write a method `safeHead` just handle `NonEmpty` List, and it is safe at compile time.

``````import SafeList._

def safeHead[A](list: SafeList[A, Size.NonEmpty.type]): A = list match
When a Nil is passed to `safeHead`, compiler will point it out:
``````safeHead(Nil)
```Found:    (Main.SafeList.Nil : Main.SafeList[Nothing, (Main.Size.Empty : Main.Size)])
Try it online at Scastie: https://scastie.scala-lang.org/jcouyang/yGQTSUJ6SN2P2oUsfWu9zw/1 Or clone the repo and `sbt test`: https://github.com/jcouyang/meow