@@ -168,38 +168,65 @@ that problem, it is recommended that the name of an extension method is
168168preceded by a space and is also followed by a space if there are more parameters
169169to come.
170170
171- ### Extension Methods and TypeClasses
171+ ### Extension Methods and Type Classes
172172
173- The rules for expanding extension methods make sure that they work seamlessly with typeclasses . For instance, consider ` SemiGroup ` and ` Monoid ` .
173+ The rules for expanding extension methods make sure that they work seamlessly with type classes . For instance, consider ` SemiGroup ` and ` Monoid ` .
174174``` scala
175- // Two typeclasses :
175+ // Two type classes :
176176 trait SemiGroup [T ] {
177177 def (x : T ) combine(y : T ): T
178178 }
179179 trait Monoid [T ] extends SemiGroup [T ] {
180180 def unit : T
181181 }
182-
183- // An instance declaration:
184- implicit object StringMonoid extends Monoid [String ] {
185- def (x : String ) combine (y : String ): String = x.concat(y)
186- def unit : String = " "
182+ object Monoid {
183+ // An instance declaration:
184+ implicit object StringMonoid extends Monoid [String ] {
185+ def (x : String ) combine (y : String ): String = x.concat(y)
186+ def unit : String = " "
187+ }
187188 }
188189
189190 // Abstracting over a typeclass with a context bound:
190191 def sum [T : Monoid ](xs : List [T ]): T =
191192 xs.foldLeft(implicitly[Monoid [T ]].unit)(_.combine(_))
192193```
194+
193195In the last line, the call to ` _.combine(_) ` expands to ` (x1, x2) => x1.combine(x2) ` ,
194196which expands in turn to ` (x1, x2) => ev.combine(x1, x2) ` where ` ev ` is the implicit
195197evidence parameter summoned by the context bound ` [T: Monoid] ` . This works since
196198extension methods apply everywhere their enclosing object is available as an implicit.
197199
200+ To avoid having to write ` implicitly[Monoid[T]].unit ` to access the ` unit ` method in ` Monoid[T] ` ,
201+ we can make ` unit ` itself an extension method on the ` Monoid ` _ companion object_ ,
202+ as shown below:
203+
204+ ``` scala
205+ trait Monoid [T ] extends SemiGroup [T ] {
206+ def (self : Monoid .type ) unit : T
207+ }
208+ object Monoid {
209+ implicit object StringMonoid extends Monoid [String ] {
210+ def (x : String ) combine (y : String ): String = x.concat(y)
211+ def (self : Monoid .type ) unit : String = " "
212+ }
213+ }
214+ ```
215+
216+ This allows us to write ` Monoid.unit ` instead of ` implicitly[Monoid[T]].unit ` ,
217+ letting the expected type distinguish which instance we want to use:
218+
219+ ``` scala
220+ def sum [T : Monoid ](xs : List [T ]): T =
221+ xs.foldLeft(Monoid .unit)(_.combine(_))
222+ ```
223+
224+
198225### Generic Extension Classes
199226
200227As another example, consider implementations of an ` Ord ` type class with a ` minimum ` value:
201228``` scala
202- trait Ord [T ]
229+ trait Ord [T ] {
203230 def (x : T ) compareTo (y : T ): Int
204231 def (x : T ) < (y : T ) = x.compareTo(y) < 0
205232 def (x : T ) > (y : T ) = x.compareTo(y) > 0
@@ -213,7 +240,7 @@ As another example, consider implementations of an `Ord` type class with a `mini
213240 }
214241
215242 class ListOrd [T : Ord ] extends Ord [List [T ]] {
216- def (xs : List [T ]) compareTo (ys : List [T ]): Int = (xs, ys) match
243+ def (xs : List [T ]) compareTo (ys : List [T ]): Int = (xs, ys) match {
217244 case (Nil , Nil ) => 0
218245 case (Nil , _) => - 1
219246 case (_, Nil ) => + 1
0 commit comments