You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _overviews/scala3-book/ca-context-bounds.md
+26
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,7 @@ num: 61
7
7
previous-page: ca-given-using-clauses
8
8
next-page: ca-given-imports
9
9
---
10
+
<spanclass="tag tag-inline">Scala 3 only</span>
10
11
11
12
12
13
{% comment %}
@@ -22,29 +23,54 @@ In that case you don’t have to define a parameter name, and can just provide t
22
23
23
24
For example, this `maximum` method takes a _context parameter_ of type `Ord`, only to pass it on as an argument to `max`:
24
25
26
+
{% tabs context-bounds-max-named-param %}
27
+
28
+
{% tab 'Scala 3 Only' %}
29
+
25
30
```scala
26
31
defmaximum[A](xs: List[A])(usingord: Ord[A]):A=
27
32
xs.reduceLeft(max(ord))
28
33
```
29
34
35
+
{% endtab %}
36
+
37
+
{% endtabs %}
38
+
30
39
In that code the parameter name `ord` isn’t actually required; it can be passed on as an inferred argument to `max`, so you just state that `maximum` uses the type `Ord[A]` without giving it a name:
31
40
41
+
{% tabs context-bounds-no-param-name %}
42
+
43
+
{% tab 'Scala 3 Only' %}
44
+
32
45
```scala
33
46
defmaximum[A](xs: List[A])(usingOrd[A]):A=
34
47
xs.reduceLeft(max)
35
48
```
36
49
50
+
{% endtab %}
51
+
52
+
{% endtabs %}
53
+
37
54
38
55
## Context bounds
39
56
40
57
Given that background, a _context bound_ is a shorthand syntax for expressing the pattern of, “a context parameter that depends on a type parameter.”
41
58
42
59
Using a context bound, the `maximum` method can be written like this:
A bound like `: Ord` on a type parameter `A` of a method or class indicates a context parameter with `Ord[A]`.
49
75
50
76
For more information about context bounds, see the [“What are context bounds?”](https://docs.scala-lang.org/tutorials/FAQ/context-bounds.html) section of the Scala FAQ.
// Values of types Dog and Dog cannot be compared with == or !=
56
61
```
57
62
63
+
{% endtab %}
64
+
65
+
{% endtabs %}
66
+
58
67
59
68
## Enabling comparisons
60
69
61
70
There are two ways to enable this comparison using the Scala 3 `CanEqual` type class.
62
71
For simple cases like this, your class can *derive* the `CanEqual` class:
63
72
73
+
{% tabs multiversal-equality-derives-CanEqual %}
74
+
75
+
{% tab 'Scala 3 Only' %}
76
+
64
77
```scala
65
78
// Option 1
66
79
caseclassDog(name: String) derivesCanEqual
67
80
```
68
81
82
+
{% endtab %}
83
+
84
+
{% endtabs %}
85
+
69
86
As you’ll see in a few moments, when you need more flexibility you can also use this syntax:
70
87
88
+
{% tabs multiversal-equality-given-CanEqual %}
89
+
90
+
{% tab 'Scala 3 Only' %}
91
+
71
92
```scala
72
93
// Option 2
73
94
caseclassDog(name: String)
74
95
givenCanEqual[Dog, Dog] =CanEqual.derived
75
96
```
76
97
98
+
{% endtab %}
99
+
100
+
{% endtabs %}
101
+
77
102
Either of those two approaches now let `Dog` instances to be compared to each other.
78
103
79
104
@@ -82,11 +107,19 @@ Either of those two approaches now let `Dog` instances to be compared to each ot
82
107
In a more real-world example, imagine you have an online bookstore and want to allow or disallow the comparison of physical, printed books, and audiobooks.
83
108
With Scala 3 you start by enabling multiversal equality as shown in the previous example:
84
109
110
+
{% tabs multiversal-equality-strictEquality-2 %}
111
+
112
+
{% tab 'Scala 3 Only' %}
113
+
85
114
```scala
86
115
// [1] add this import, or this command line flag: -language:strictEquality
87
116
importscala.language.strictEquality
88
117
```
89
118
119
+
{% endtab %}
120
+
121
+
{% endtabs %}
122
+
90
123
Then create your domain objects as usual:
91
124
92
125
```scala
@@ -113,6 +146,10 @@ case class AudioBook(
113
146
114
147
Finally, use `CanEqual` to define which comparisons you want to allow:
0 commit comments