Skip to content

Small clarification for Multiversal Equality documentation #5348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 31, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions docs/docs/reference/multiversal-equality.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ Universal equality is convenient but also dangerous since it
undermines type safety. Say you have an erroneous program where
a value `y` has type `S` instead of the expected type `T`.

val x = ... // of type T
val y = ... // of type S, but should be T
x == y // typechecks, will always yield false
```scala
val x = ... // of type T
val y = ... // of type S, but should be T
x == y // typechecks, will always yield false
```

If all you do with `y` is compare it to other values of type `T`, the program will
typecheck but probably give unexpected results.
Expand All @@ -26,7 +28,9 @@ restrict the types that are legal in comparisons. The example above
would not typecheck if an implicit was declared like this for type `T`
(or an analogous one for type `S`):

implicit def eqT: Eq[T, T] = Eq
```scala
implicit def eqT: Eq[T, T] = Eq
```

This definition effectively says that value of type `T` can (only) be
compared with `==` or `!=` to other values of type `T`. The definition
Expand All @@ -36,22 +40,26 @@ the negation of `equals`. The right hand side of the definition is a value
that has any `Eq` instance as its type. Here is the definition of class
`Eq` and its companion object:

package scala
import annotation.implicitNotFound
```scala
package scala
import annotation.implicitNotFound

@implicitNotFound("Values of types ${L} and ${R} cannot be compared with == or !=")
sealed trait Eq[-L, -R]
@implicitNotFound("Values of types ${L} and ${R} cannot be compared with == or !=")
sealed trait Eq[-L, -R]

object Eq extends Eq[Any, Any]
object Eq extends Eq[Any, Any]
```

One can have several `Eq` instances for a type. For example, the four
definitions below make values of type `A` and type `B` comparable with
each other, but not comparable to anything else:

implicit def eqA : Eq[A, A] = Eq
implicit def eqB : Eq[B, B] = Eq
implicit def eqAB: Eq[A, B] = Eq
implicit def eqBA: Eq[B, A] = Eq
```scala
implicit def eqA : Eq[A, A] = Eq
implicit def eqB : Eq[B, B] = Eq
implicit def eqAB: Eq[A, B] = Eq
implicit def eqBA: Eq[B, A] = Eq
```

(As usual, the names of the implicit definitions don't matter, we have
chosen `eqA`, ..., `eqBA` only for illustration).
Expand All @@ -66,7 +74,9 @@ There's also a "fallback" instance named `eqAny` that allows comparisons
over all types that do not themselves have an `Eq` instance. `eqAny` is
defined as follows:

def eqAny[L, R]: Eq[L, R] = Eq
```scala
def eqAny[L, R]: Eq[L, R] = Eq
```

Even though `eqAny` is not declared implicit, the compiler will still
construct an `eqAny` instance as answer to an implicit search for the
Expand All @@ -78,7 +88,9 @@ if this is of no concern one can disable `eqAny` by enabling the language
feature `strictEquality`. As for all language features this can be either
done with an import

import scala.language.strictEquality
```scala
import scala.language.strictEquality
```

or with a command line option `-language:strictEquality`.

Expand All @@ -94,11 +106,11 @@ The precise rules for equality checking are as follows.
a definition of lifting.

2. The usual rules for implicit search apply also to `Eq` instances,
with one modification: An instance of `scala.Eq.eqAny[T, U]` is
constructed if neither `T` nor `U` have a reflexive `Eq`
instance themselves. Here, a type `T` has a reflexive `Eq`
instance if the implicit search for `Eq[T, T]` succeeds
and constructs an instance different from `eqAny`.
with one modification: If the `strictEquality` feature is not enabled,
an instance of `scala.Eq.eqAny[T, U]` is constructed if neither `T`
nor `U` have a reflexive `Eq` instance themselves. Here, a type `T`
has a reflexive `Eq` instance if the implicit search for `Eq[T, T]`
succeeds and constructs an instance different from `eqAny`.

Here _lifting_ a type `S` means replacing all references to abstract types
in covariant positions of `S` by their upper bound, and to replacing
Expand Down