Skip to content

Commit 006752e

Browse files
committed
Doc page
1 parent 3a35742 commit 006752e

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

docs/docs/reference/opaques.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
layout: doc-page
3+
title: "Opaque Type Aliases"
4+
---
5+
6+
Opaque types aliases provide type abstraction without any overhead. Example:
7+
8+
```scala
9+
opaque type Logarithm = Double
10+
```
11+
12+
This introduces `Logarithm` as a new type, which is implemented as `Double` but is different from it. The fact that `Logarithm` is the same as `Double` is only known in the companion object of `Logarithm`. Here is a possible companion object:
13+
14+
```scala
15+
object Logarithm {
16+
17+
// These are the ways to lift to the logarithm type
18+
def apply(d: Double): Logarithm = math.log(d)
19+
20+
def safe(d: Double): Option[Logarithm] =
21+
if (d > 0.0) Some(math.log(d)) else None
22+
23+
// This is the first way to unlift the logarithm type
24+
def exponent(l: Logarithm): Double = l
25+
26+
// Extension methods define opaque types' public APIs
27+
implicit class LogarithmOps(val `this`: Logarithm) extends AnyVal {
28+
// This is the second way to unlift the logarithm type
29+
def toDouble: Double = math.exp(`this`)
30+
def +(that: Logarithm): Logarithm = Logarithm(math.exp(`this`) + math.exp(that))
31+
def *(that: Logarithm): Logarithm = Logarithm(`this` + that)
32+
}
33+
}
34+
```
35+
36+
The companion object contains with the `apply` and `safe` methods ways to convert from doubles to `Logarithm` values. It also adds an `exponent` function and a decorator that implements `+` and `*` on logarithm values, as well as a conversion `toDouble`. All this is possible because within object `Logarithm`, the type `Logarithm` is just an alias of `Double`.
37+
38+
Outside the companion object, `Logarithm` is treated as a new abstract type. So the
39+
following operations would be valid because they use functionality implemented in the `Logarithm` object.
40+
41+
```scala
42+
val l = Logarithm(1.0)
43+
val l3 = l * l2
44+
val l4 = l + l2
45+
```
46+
47+
But the following operations would lead to type errors:
48+
49+
```scala
50+
val d: Double = l // error: found: Logarithm, required: Double
51+
val l2: Logarithm = 1.0 // error: found: Double, required: Logarithm
52+
l * 2 // error: found: Int(2), required: Logarithm
53+
l / l2 // error: `/` is not a member fo Logarithm
54+
```
55+
56+
For more details, see [Scala SIP 35](https://docs.scala-lang.org/sips/opaque-types.html).

docs/sidebar.yml

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ sidebar:
4949
url: docs/reference/inline.html
5050
- title: Meta Programming
5151
url: docs/reference/principled-meta-programming.html
52+
- title: Opaque Type Aliases
53+
url: docs/reference/opaques.html
5254
- title: By-Name Implicits
5355
url: docs/reference/implicit-by-name-parameters.html
5456
- title: Auto Parameter Tupling

0 commit comments

Comments
 (0)