Skip to content

Commit cb05b58

Browse files
authored
Merge pull request #10 from tegonal/doc-opaque-type-alias
doc(opaque type alias): revise text, remove workaround
2 parents ed3bc4a + 870173c commit cb05b58

File tree

1 file changed

+18
-16
lines changed

1 file changed

+18
-16
lines changed

docs/docs/reference/other-new-features/opaques.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ object Logarithms {
1212

1313
object Logarithm {
1414

15-
// These are the ways to lift to the logarithm type
15+
// These are the two ways to lift to the Logarithm type
16+
1617
def apply(d: Double): Logarithm = math.log(d)
1718

1819
def safe(d: Double): Option[Logarithm] =
@@ -28,19 +29,22 @@ object Logarithms {
2829
}
2930
```
3031

31-
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 scope where
32-
`Logarithm` is defined which in this case is object `Logarithms`.
33-
34-
The public API of `Logarithm` consists of the `apply` and `safe` methods that convert from doubles to `Logarithm` values, an extension method `toDouble` that converts the other way,
35-
and operations `+` and `*` on logarithm values. The implementations of these functions
36-
type-check because within object `Logarithms`, the type `Logarithm` is just an alias of `Double`.
32+
This introduces `Logarithm` as a new abstract type, which is implemented as `Double`.
33+
The fact that `Logarithm` is the same as `Double` is only known in the scope where
34+
`Logarithm` is defined which in the above example corresponds to the object `Logarithms`.
35+
Or in other words, within the scope it is treated as type alias, but this is opaque to the outside world
36+
where in consequence `Logarithm` is treated as own type and has nothing to do with `Double`.
3737

38-
Outside its scope, `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.
38+
The public API of `Logarithm` consists of the `apply` and `safe` methods defined in the companion object.
39+
They convert from `Double`s to `Logarithm` values. Moreover, a collective extension `logarithmOps` provides the extension methods `toDouble` that converts the other way,
40+
and operations `+` and `*` on `Logarithm` values.
41+
As a reminder, the implementations of these functions
42+
type-check because within the object `Logarithms`, the type `Logarithm` is just a type alias of `Double`.
43+
Outside of its scope, `Logarithm` is treated as a new abstract type. So the
44+
following operations would be valid because they use functionality implemented in the `Logarithms` object.
4045

4146
```scala
42-
import Logarithms._
43-
import Predef.{any2stringadd => _, _}
47+
import Logarithms.Logarithm
4448

4549
val l = Logarithm(1.0)
4650
val l2 = Logarithm(2.0)
@@ -54,11 +58,9 @@ But the following operations would lead to type errors:
5458
val d: Double = l // error: found: Logarithm, required: Double
5559
val l2: Logarithm = 1.0 // error: found: Double, required: Logarithm
5660
l * 2 // error: found: Int(2), required: Logarithm
57-
l / l2 // error: `/` is not a member fo Logarithm
61+
l / l2 // error: `/` is not a member of Logarithm
5862
```
5963

60-
Aside: the `any2stringadd => _` import suppression is necessary since otherwise the universal `+` operation in `Predef` would take precedence over the `+` extension method in `logarithmOps`. We plan to resolve this wart by eliminating `any2stringadd`.
61-
6264
### Bounds For Opaque Type Aliases
6365

6466
Opaque type aliases can also come with bounds. Example:
@@ -81,7 +83,7 @@ object Access {
8183
val ReadOrWrite: PermissionChoice = Read | Write
8284
}
8385
```
84-
The `Access` object defines three opaque types:
86+
The `Access` object defines three opaque type aliases:
8587

8688
- `Permission`, representing a single permission,
8789
- `Permissions`, representing a set of permissions with the meaning "all of these permissions granted",
@@ -98,7 +100,7 @@ Because of that, the `|` extension method in `Access` does not cause infinite re
98100
Also, the definition of `ReadWrite` must use `|`,
99101
even though an equivalent definition outside `Access` would use `&`.
100102

101-
All three opaque types have the same underlying representation type `Int`. The
103+
All three opaque type aliases have the same underlying representation type `Int`. The
102104
`Permission` type has an upper bound `Permissions & PermissionChoice`. This makes
103105
it known outside the `Access` object that `Permission` is a subtype of the other
104106
two types. Hence, the following usage scenario type-checks.

0 commit comments

Comments
 (0)