Skip to content

Commit 9c91536

Browse files
committed
Section on ADTs
1 parent aaf24e6 commit 9c91536

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

docs/docs/reference/adts.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Algebraic Data Types
2+
3+
The `enum` concept is general enough to also support algebraic data
4+
types (ADTs) and their generalized version (GADTs). Here's an example
5+
how an `Option` type can be represented as an ADT:
6+
7+
```scala
8+
enum Option[+T] {
9+
case Some[+T](x: T)
10+
case None
11+
}
12+
```
13+
14+
This example introduces `Option` enum class with a covariant type
15+
parameter `T`, together with two cases, `Some` and `None`. `Some` is
16+
parameterized with a type parameter `T` and a value parameter `x`. It
17+
is a shorthand for writing a case class that extends `Option`. Since
18+
`None` is not parameterized it is treated as a normal enum value.
19+
20+
The `extends` clauses that were omitted in the example above can also
21+
be given explicitly:
22+
23+
```scala
24+
enum Option[+T] {
25+
case Some[T](x: T) extends Option[T]
26+
case None extends Option[Nothing]
27+
}
28+
```
29+
30+
Note that the parent type of `None` is inferred as
31+
`List[Nothing]`. Generally, all covariant type parameters of the enum
32+
class are minimized in a compiler-generated extends clause whereas all
33+
contravariant type parameters are maximized. If `Option` was non-variant,
34+
you'd need to give the extends clause of `None` explicitly.
35+
36+
As for normal enum values, the cases of an `enum` are all defined in
37+
the `enum`s companion object. So it's `Option.Some` and `Option.None`
38+
unless the definitions are "pulled out" with an import:
39+
40+
```scala
41+
scala> Option.Some("hello")
42+
val res1: t2.Option[String] = Some(hello)
43+
scala> Option.None
44+
val res2: t2.Option[Nothing] = None
45+
```
46+
47+
Note that the type of the expressions above is always `Option`. That
48+
is, the implementation case classes are not visible in the result
49+
types of their `apply` methods. This is a subtle difference with
50+
respect to normal case classes. The classes making up the cases do
51+
exist, and can be unvealed by constructing them directly with a `new`.
52+
53+
```scala
54+
val res3: t2.Option.Some[Int] = Some(2)
55+
scala> scala> new Option.Some(2)
56+
```
57+
58+
59+
60+
61+

tests/pos/reference/adts.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
object t1 {
2+
3+
enum Option[+T] {
4+
case Some[T](x: T)
5+
case None
6+
}
7+
8+
}
9+
10+
object t2 {
11+
12+
enum Option[+T] {
13+
case Some[T](x: T) extends Option[T]
14+
case None extends Option[Nothing]
15+
}
16+
17+
18+
}
19+
20+
enum Color(val rgb: Int) {
21+
case Red extends Color(0xFF0000)
22+
case Green extends Color(0x00FF00)
23+
case Blue extends Color(0x0000FF)
24+
case Mix(mix: Int) extends Color(mix)
25+
}
26+

0 commit comments

Comments
 (0)