Skip to content

Commit a5c8aef

Browse files
author
Arnaud ESTEVE
committed
trying to rewrite typeclasses-new
1 parent 0b90ec1 commit a5c8aef

File tree

1 file changed

+51
-7
lines changed

1 file changed

+51
-7
lines changed

docs/docs/reference/contextual/typeclasses-new.md

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ layout: doc-page
33
title: "Implementing Typeclasses"
44
---
55

6-
Given instances, extension methods and context bounds
7-
allow a concise and natural expression of _typeclasses_. Typeclasses are just traits
8-
with canonical implementations defined by given instances. Here are some examples of standard typeclasses:
6+
In Scala 3, _typeclasses_ are just traits whose implementation are defined by given instances.
7+
Here are some examples of standard typeclasses:
98

109
### Semigroups and monoids:
1110

11+
Here's the `Monoid` typeclass definition:
12+
1213
```scala
1314
trait SemiGroup[T] {
1415
@infix def (x: T) combine (y: T): T
@@ -17,25 +18,65 @@ trait SemiGroup[T] {
1718
trait Monoid[T] extends SemiGroup[T] {
1819
def unit: T
1920
}
21+
```
2022

21-
object Monoid {
22-
def apply[T] with (m: Monoid[T]) = m
23-
}
23+
An implementation of this `Monoid` typeclass for the type `String` can be the following:
2424

25+
```scala
2526
given as Monoid[String] {
2627
def (x: String) combine (y: String): String = x.concat(y)
2728
def unit: String = ""
2829
}
30+
```
2931

32+
Whereas for the type `Int` one could write the following:
33+
```scala
3034
given as Monoid[Int] {
3135
def (x: Int) combine (y: Int): Int = x + y
3236
def unit: Int = 0
3337
}
38+
```
3439

35-
def sum[T: Monoid](xs: List[T]): T =
40+
This monoid can now be used as _context bound_ in the following `combineAll` method:
41+
42+
```scala
43+
def combineAll[T: Monoid](xs: List[T]): T =
44+
xs.foldLeft(summon[Monoid[T]].unit)(_ combine _)
45+
```
46+
47+
To get rid of the `summon[...]` we can define a `Monoid` object as follows:
48+
49+
```scala
50+
object Monoid {
51+
def apply[T] with (m: Monoid[T]) = m
52+
}
53+
```
54+
55+
Which would allow to re-write the `combineAll` method this way:
56+
57+
```scala
58+
def combineAll[T: Monoid](xs: List[T]): T =
3659
xs.foldLeft(Monoid[T].unit)(_ combine _)
3760
```
3861

62+
We can also benefit from [extension methods](extension-methods-new.html) to make this `combineAll` function accessible as a method on the `List` type:
63+
64+
65+
```scala
66+
def [T: Monoid](xs: List[T]).combineAll: T =
67+
xs.foldLeft(Monoid[T].unit)(_ combine _)
68+
```
69+
70+
Which allows one to write:
71+
72+
```scala
73+
assert("ab" == List("a", "b").combineAll)
74+
```
75+
or:
76+
```scala
77+
assert(3 == List(1, 2).combineAll)
78+
```
79+
3980
### Functors and monads:
4081

4182
```scala
@@ -64,3 +105,6 @@ given readerMonad[Ctx] as Monad[[X] =>> Ctx => X] {
64105
ctx => x
65106
}
66107
```
108+
109+
110+
The conjunction of given instances, extension methods and context bounds allow a concise and natural expression of _typeclasses_

0 commit comments

Comments
 (0)