forked from scala/scala3
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
aa292d7
commit 5244d76
Showing
2 changed files
with
87 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Algebraic Data Types | ||
|
||
The `enum` concept is general enough to also support algebraic data | ||
types (ADTs) and their generalized version (GADTs). Here's an example | ||
how an `Option` type can be represented as an ADT: | ||
|
||
```scala | ||
enum Option[+T] { | ||
case Some[+T](x: T) | ||
case None | ||
} | ||
``` | ||
|
||
This example introduces `Option` enum class with a covariant type | ||
parameter `T`, together with two cases, `Some` and `None`. `Some` is | ||
parameterized with a type parameter `T` and a value parameter `x`. It | ||
is a shorthand for writing a case class that extends `Option`. Since | ||
`None` is not parameterized it is treated as a normal enum value. | ||
|
||
The `extends` clauses that were omitted in the example above can also | ||
be given explicitly: | ||
|
||
```scala | ||
enum Option[+T] { | ||
case Some[T](x: T) extends Option[T] | ||
case None extends Option[Nothing] | ||
} | ||
``` | ||
|
||
Note that the parent type of `None` is inferred as | ||
`List[Nothing]`. Generally, all covariant type parameters of the enum | ||
class are minimized in a compiler-generated extends clause whereas all | ||
contravariant type parameters are maximized. If `Option` was non-variant, | ||
you'd need to give the extends clause of `None` explicitly. | ||
|
||
As for normal enum values, the cases of an `enum` are all defined in | ||
the `enum`s companion object. So it's `Option.Some` and `Option.None` | ||
unless the definitions are "pulled out" with an import: | ||
|
||
```scala | ||
scala> Option.Some("hello") | ||
val res1: t2.Option[String] = Some(hello) | ||
scala> Option.None | ||
val res2: t2.Option[Nothing] = None | ||
``` | ||
|
||
Note that the type of the expressions above is always `Option`. That | ||
is, the implementation case classes are not visible in the result | ||
types of their `apply` methods. This is a subtle difference with | ||
respect to normal case classes. The classes making up the cases do | ||
exist, and can be unvealed by constructing them directly with a `new`. | ||
|
||
```scala | ||
val res3: t2.Option.Some[Int] = Some(2) | ||
scala> scala> new Option.Some(2) | ||
``` | ||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
object t1 { | ||
|
||
enum Option[+T] { | ||
case Some[T](x: T) | ||
case None | ||
} | ||
|
||
} | ||
|
||
object t2 { | ||
|
||
enum Option[+T] { | ||
case Some[T](x: T) extends Option[T] | ||
case None extends Option[Nothing] | ||
} | ||
|
||
|
||
} | ||
|
||
enum Color(val rgb: Int) { | ||
case Red extends Color(0xFF0000) | ||
case Green extends Color(0x00FF00) | ||
case Blue extends Color(0x0000FF) | ||
case Mix(mix: Int) extends Color(mix) | ||
} | ||
|