Skip to content

Commit bf7b0e5

Browse files
committed
Update ghost section with real life example
1 parent ffbedef commit bf7b0e5

File tree

1 file changed

+27
-18
lines changed

1 file changed

+27
-18
lines changed

docs/blog/_posts/2018-03-05-seventh-dotty-milestone-release.md

+27-18
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Let's consider how `Option` can be represented as an enum. Previously using an e
3939
enum class Option[+T] {
4040
def isDefined: Boolean
4141
}
42+
4243
object Option {
4344
case Some[+T](x: T) {
4445
def isDefined = true
@@ -68,32 +69,40 @@ object Option {
6869
}
6970
```
7071

71-
You can visit our website for more information about [enumerations](/docs/reference/enums/enums.html)
72-
and how we can use them to model [Algebraic Data Types](/docs/reference/enums/adts.html).
7372

74-
### Ghost terms [#3342](https://github.com/lampepfl/dotty/pull/3342) and removing phantom types [#3410](https://github.com/lampepfl/dotty/pull/3410)
75-
The keyword `ghost` can be placed on parameters, `val` and `def` to enforce that no reference to
76-
those terms is ever used (recursively). As they are never used, they can safely be removed during compilation.
77-
Ghost terms replace _phantom types_: they have similar semantics, but with the added advantage that any type can be a ghost parameter. They can be used to add implicit type constraints that are only relevant at compilation time.
73+
For more information about [Enumerations](/docs/reference/enums/enums.html) and how to use them to
74+
model [Algebraic Data Types](/docs/reference/enums/adts.html), visit the respective sections in our
75+
documentation.
7876

79-
```scala
80-
// A function that requires an implicit evidence of type X =:= Y but never uses it.
81-
// The parameter will be removed and the argument will not be evaluated.
82-
def apply(implicit ghost ev: X =:= Y) =
83-
foo(ev) // `ev` can be an argument to foo as foo will also never use it
84-
def foo(ghost x: X =:= Y) = ()
85-
```
77+
### Ghost terms [#3342](https://github.com/lampepfl/dotty/pull/3342)
78+
The `ghost` modifier can be used on parameters, `val` and `def` to enforce that no reference to
79+
those terms is ever used. As they are never used, they can safely be removed during compilation.
8680

87-
The previous code will be transformed to the following:
81+
One particular use case is to add implicit type constraints that are only relevant at compilation
82+
time. For example, let's consider the following implementation of `flatten`.
8883

8984
```scala
90-
def apply() = // ghost parameter will be removed
91-
foo() // foo is called without the ghost parameter
92-
def foo() = () // ghost parameter will be removed
85+
class List[X] {
86+
def flatten[Y](implicit ghost ev: X <:< List[Y]): List[Y] = {
87+
val buffer = new mutable.ListBuffer[Y]
88+
this.foreach(e => buffer ++= e.asInstanceOf[List[Y]])
89+
buffer.toList
90+
}
91+
}
92+
93+
List(List(1, 2), List(3)).flatten // List(List(1, 2, 3))
94+
List(1, 2, 3).flatten // error: Cannot prove that Int <:< List[Y]
9395
```
9496

95-
[Documentation](/docs/reference/ghost-terms.html)
97+
The implicit evidence `ev` is only used to constrain the type parameter `X` of `List` such that we
98+
can safely cast from `X` to `List[_]`. The usage of the `ghost` modifier ensures that the evidence
99+
is not used and can be safely removed at compilation time.
100+
101+
For more information, visit the [Ghost Terms](/docs/reference/ghost-terms.html) section of our
102+
documentation.
96103

104+
**Note**: Ghost terms replace _phantom types_: they have similar semantics, but with the added
105+
advantage that any type can be a ghost parameter. See [#3410](https://github.com/lampepfl/dotty/pull/3410).
97106

98107
## Trying out Dotty
99108
### Scastie

0 commit comments

Comments
 (0)