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
A _type class_ is an abstract, parameterized type that lets you add new behavior to any closed data type without using sub-typing.
14
13
If you are coming from Java, you can think of type classes as something like [`java.util.Comparator[T]`][comparator].
15
14
@@ -21,99 +20,171 @@ A type class is useful in multiple use-cases, for example:
21
20
- Expressing how a type you don’t own---from the standard library or a third-party library---conforms to such behavior
22
21
- Expressing such a behavior for multiple types without involving sub-typing relationships between those types
23
22
24
-
In Scala 3, type classes are just traits with one or more parameters whose implementations are provided by `given` instances.
25
-
26
-
23
+
Type classes are traits with one or more parameters whose implementations are provided as `given` instances in Scala 3 or `implicit` values in Scala 2.
27
24
28
25
## Example
29
26
30
-
For example, `Show` is a well-known type class in Haskell, and the following code shows one way to implement it in Scala 3.
31
-
If you imagine that Scala classes don’t have a `toString` method, you can define a `Show` type class to add this behavior to any class that you want to be able to convert to a custom string.
27
+
For example, `Show` is a well-known type class in Haskell, and the following code shows one way to implement it in Scala.
28
+
If you imagine that Scala classes don’t have a `toString` method, you can define a `Show` type class to add this behavior to any type that you want to be able to convert to a custom string.
32
29
33
30
### The type class
34
31
35
32
The first step in creating a type class is to declare a parameterized trait that has one or more abstract methods.
36
33
Because `Showable` only has one method named `show`, it’s written like this:
37
34
35
+
{% tabs 'definition' class=tabs-scala-version %}
36
+
{% tab 'Scala 2' %}
37
+
```scala
38
+
// a type class
39
+
traitShowable[A] {
40
+
defshow(a: A):String
41
+
}
42
+
```
43
+
{% endtab %}
44
+
{% tab 'Scala 3' %}
38
45
```scala
39
46
// a type class
40
47
traitShowable[A]:
41
48
extension(a: A) defshow:String
42
49
```
50
+
{% endtab %}
51
+
{% endtabs %}
43
52
44
53
This is the Scala 3 way of saying that any type that implements this trait must define how the `show` method works.
45
54
Notice that the syntax is very close to a normal trait:
46
55
56
+
{% tabs 'trait' class=tabs-scala-version %}
57
+
{% tab 'Scala 2' %}
58
+
```scala
59
+
// a trait
60
+
traitShow {
61
+
defshow:String
62
+
}
63
+
```
64
+
{% endtab %}
65
+
{% tab 'Scala 3' %}
47
66
```scala
48
67
// a trait
49
68
traitShow:
50
69
defshow:String
51
70
```
71
+
{% endtab %}
72
+
{% endtabs %}
52
73
53
74
There are a few important things to point out:
54
75
55
76
1. Type-classes like `Showable` take a type parameter `A` to say which type we provide the implementation of `show` for; in contrast, normal traits like `Show` do not.
56
77
2. To add the show functionality to a certain type `A`, the normal trait requires that `A extends Show`, while for type-classes we require to have an implementation of `Showable[A]`.
57
-
3.To allow the same method calling syntax in both `Showable` that mimics the one of `Show`, we define `Showable.show` as an extension method.
78
+
3.In Scala 3, to allow the same method calling syntax in both `Showable` that mimics the one of `Show`, we define `Showable.show` as an extension method.
58
79
59
80
### Implement concrete instances
60
81
61
82
The next step is to determine what classes in your application `Showable` should work for, and then implement that behavior for them.
62
83
For instance, to implement `Showable` for this `Person` class:
As shown, this is defined as an extension method on the `Person` class, and it uses the reference `p` inside the body of the `show` method.
112
+
{% endtab %}
113
+
{% endtabs %}
78
114
79
115
### Using the type class
80
116
81
117
Now you can use this type class like this:
82
118
119
+
{% tabs 'usage' class=tabs-scala-version %}
120
+
{% tab 'Scala 2' %}
121
+
```scala
122
+
valperson=Person("John", "Doe")
123
+
println(showablePerson.show(person))
124
+
```
125
+
126
+
Not that in practice, type classes are typically used with values whose type is unknown, unlike the type `Person`, as shown in the next section.
127
+
{% endtab %}
128
+
{% tab 'Scala 3' %}
83
129
```scala
84
130
valperson=Person("John", "Doe")
85
131
println(person.show)
86
132
```
133
+
{% endtab %}
134
+
{% endtabs %}
87
135
88
136
Again, if Scala didn’t have a `toString` method available to every class, you could use this technique to add `Showable` behavior to any class that you want to be able to convert to a `String`.
89
137
90
138
### Writing methods that use the type class
91
139
92
140
As with inheritance, you can define methods that use `Showable` as a type parameter:
0 commit comments