From 8deb3340cf1f607f63da5bb95c19aa8ecbc40805 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Wed, 31 Oct 2018 14:56:12 +0100 Subject: [PATCH] Small clarification for Multiversal Equality documentation --- docs/docs/reference/multiversal-equality.md | 52 +++++++++++++-------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/docs/docs/reference/multiversal-equality.md b/docs/docs/reference/multiversal-equality.md index 5a01d8943c56..709ee2f1543e 100644 --- a/docs/docs/reference/multiversal-equality.md +++ b/docs/docs/reference/multiversal-equality.md @@ -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. @@ -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 @@ -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). @@ -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 @@ -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`. @@ -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