Skip to content

Commit e64c62c

Browse files
committed
Extending and polishing the example
- Add straight extensions of type classes, i.e. implementation inherits type class directly. - Rename common as an identifier to commons - Drop `Extension` type.
1 parent cb09305 commit e64c62c

File tree

1 file changed

+88
-50
lines changed

1 file changed

+88
-50
lines changed

tests/pos/typeclass-encoding2.scala

+88-50
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** A possible type class encoding for
1+
/** 1. Simple type classes with monomorphic implementations and direct extensions.
22
33
trait SemiGroup extends TypeClass {
44
def add(that: This): This
@@ -23,88 +23,122 @@
2323
def unit = ""
2424
}
2525
26+
enum Nat extends Monoid {
27+
case Z
28+
case S(n: Nat)
29+
30+
def add(that: Nat): Nat = this match {
31+
case S => that
32+
case S(n) => S(n.add(that))
33+
}
34+
}
35+
common {
36+
def unit = Z
37+
}
38+
2639
def sum[T: Monoid](xs: List[T]): T =
2740
(Monod.impl[T].unit /: xs)(_ `add` _)
2841
*/
2942
object runtime {
3043

3144
trait TypeClass {
32-
val common: TypeClassCommon
33-
type This = common.This
45+
val commons: TypeClassCommon
46+
type This = commons.This
3447
}
3548

3649
trait TypeClassCommon { self =>
3750
type This
3851
type Instance <: TypeClass
39-
def inject(x: This): Instance { val common: self.type }
52+
def inject(x: This): Instance { val commons: self.type }
4053
}
4154

4255
trait TypeClassCompanion {
43-
type Impl[T] <: Extension[T]
56+
type Impl[T] <: TypeClassCommon { type This = T }
4457
def impl[T](implicit ev: Impl[T]): Impl[T] = ev
4558
}
4659

47-
trait Extension[From] extends TypeClassCommon {
48-
type This = From
49-
}
50-
5160
implicit def inject[From](x: From)
52-
(implicit ev: Extension[From]): ev.Instance { type This = From } =
61+
(implicit ev: TypeClassCommon { type This = From }): ev.Instance { type This = From } =
5362
ev.inject(x)
5463
}
5564
import runtime._
5665

5766
object semiGroups {
5867

5968
trait SemiGroup extends TypeClass {
60-
val common: SemiGroupCommon
61-
import common._
69+
val commons: SemiGroupCommon
70+
import commons._
6271
def add(that: This): This
6372
}
6473
trait SemiGroupCommon extends TypeClassCommon {
6574
type Instance <: SemiGroup
6675
}
6776
object SemiGroup extends TypeClassCompanion {
68-
type Impl[T] = Extension[T] with SemiGroupCommon
77+
type Impl[T] = SemiGroupCommon { type This = T }
6978
}
7079

7180
trait Monoid extends SemiGroup {
72-
val common: MonoidCommon
73-
import common._
81+
val commons: MonoidCommon
82+
import commons._
7483
}
7584
trait MonoidCommon extends SemiGroupCommon {
7685
type Instance <: Monoid
7786
def unit: This
7887
}
7988
object Monoid extends TypeClassCompanion {
80-
type Impl[T] = Extension[T] with MonoidCommon
89+
type Impl[T] = MonoidCommon { type This = T }
8190
}
8291

83-
implicit object IntOps extends Extension[Int] with MonoidCommon {
92+
implicit object IntOps extends MonoidCommon {
8493
type This = Int
8594
type Instance = Monoid
8695
def unit: Int = 0
8796
def inject($this: Int) = new Monoid {
88-
val common: IntOps.this.type = IntOps.this
97+
val commons: IntOps.this.type = IntOps.this
8998
def add(that: This): This = $this + that
9099
}
91100
}
92101

93-
implicit object StringOps extends Extension[String] with MonoidCommon {
102+
implicit object StringOps extends MonoidCommon {
94103
type This = String
95104
type Instance = Monoid
96105
def unit = ""
97106
def inject($this: String) = new Monoid {
98-
val common: StringOps.this.type = StringOps.this
107+
val commons: StringOps.this.type = StringOps.this
99108
def add(that: This): This = $this.concat(that)
100109
}
101110
}
102111

112+
enum Nat extends Monoid {
113+
case Z
114+
case S(n: Nat)
115+
116+
def add(that: Nat): Nat = this match {
117+
case Z => that
118+
case S(n) => S(n.add(that))
119+
}
120+
121+
val commons: Nat.type = Nat
122+
}
123+
object Nat extends MonoidCommon {
124+
type This = Nat
125+
type Instance = Nat
126+
def unit = Nat.Z
127+
def inject($this: Nat) = $this
128+
}
129+
import Nat.{Z, S}
130+
131+
implicit def NatOps: Nat.type = Nat
132+
103133
def sum[T](xs: List[T])(implicit ev: Monoid.Impl[T]) =
104134
(Monoid.impl[T].unit /: xs)((x, y) => x `add` y)
135+
136+
sum(List(1, 2, 3))
137+
sum(List("hello ", "world!"))
138+
sum(List(Z, S(Z), S(S(Z))))
105139
}
106140

107-
/** Encoding for
141+
/** 2. Generic implementations of simple type classes.
108142
109143
trait Ord extends TypeClass {
110144
def compareTo(that: This): Int
@@ -144,8 +178,8 @@ object semiGroups {
144178
object ord {
145179

146180
trait Ord extends TypeClass {
147-
val common: OrdCommon
148-
import common._
181+
val commons: OrdCommon
182+
import commons._
149183
def compareTo(that: This): Int
150184
def < (that: This) = compareTo(that) < 0
151185
def > (that: This) = compareTo(that) > 0
@@ -155,27 +189,28 @@ object ord {
155189
def minimum: This
156190
}
157191
object Ord extends TypeClassCompanion {
158-
type Impl[T] = Extension[T] with OrdCommon
192+
type Impl[T] = OrdCommon { type This = T }
159193
}
160194

161-
implicit object IntOrd extends Extension[Int] with OrdCommon {
195+
implicit object IntOrd extends OrdCommon {
162196
type This = Int
163197
type Instance = Ord
164198
val minimum: Int = Int.MinValue
165199
def inject($this: Int) = new Ord {
166-
val common: IntOrd.this.type = IntOrd.this
200+
val commons: IntOrd.this.type = IntOrd.this
201+
import commons._
167202
def compareTo(that: This): Int =
168203
if (this < that) -1 else if (this > that) +1 else 0
169204
}
170205
}
171206

172-
class ListOrd[T](implicit ev: Ord.Impl[T])
173-
extends Extension[List[T]] with OrdCommon { self =>
207+
class ListOrd[T](implicit ev: Ord.Impl[T]) extends OrdCommon { self =>
174208
type This = List[T]
175209
type Instance = Ord
176210
def minimum: List[T] = Nil
177211
def inject($this: List[T]) = new Ord {
178-
val common: self.type = self
212+
val commons: self.type = self
213+
import commons._
179214
def compareTo(that: List[T]): Int = ($this, that) match {
180215
case (Nil, Nil) => 0
181216
case (Nil, _) => -1
@@ -197,9 +232,13 @@ object ord {
197232
val smallest = Ord.impl[T].minimum
198233
(smallest /: xs)(min)
199234
}
235+
236+
inf(List[Int]())
237+
inf(List(List(1, 2), List(1, 2, 3)))
238+
inf(List(List(List(1), List(2)), List(List(1), List(2), List(3))))
200239
}
201240

202-
/** Encoding for
241+
/** 3. Higher-kinded type classes
203242
204243
trait Functor[A] extends TypeClass1 {
205244
def map[B](f: A => B): This[B]
@@ -234,75 +273,74 @@ object ord {
234273
object runtime1 {
235274

236275
trait TypeClass1 {
237-
val common: TypeClassCommon1
238-
type This = common.This
276+
val commons: TypeClassCommon1
277+
type This = commons.This
239278
}
240279

241280
trait TypeClassCommon1 { self =>
242281
type This[X]
243282
type Instance[X] <: TypeClass1
244-
def inject[A](x: This[A]): Instance[A] { val common: self.type }
283+
def inject[A](x: This[A]): Instance[A] { val commons: self.type }
245284
}
246285

247286
trait TypeClassCompanion1 {
248-
type Impl[T[_]] <: Extension1[T]
287+
type Impl[T[_]] <: TypeClassCommon1 { type This = T }
249288
def impl[T[_]](implicit ev: Impl[T]): Impl[T] = ev
250289
}
251290

252-
trait Extension1[From[_]] extends TypeClassCommon1 {
253-
type This[X] = From[X]
254-
}
255-
256291
implicit def inject1[A, From[_]](x: From[A])
257-
(implicit ev: Extension1[From]): ev.Instance[A] { type This = From } =
292+
(implicit ev: TypeClassCommon1 { type This = From }): ev.Instance[A] { type This = From } =
258293
ev.inject(x)
259294
}
260295
import runtime1._
261296

262297
object functors {
263298

264299
trait Functor[A] extends TypeClass1 {
265-
val common: FunctorCommon
266-
import common._
300+
val commons: FunctorCommon
301+
import commons._
267302
def map[B](f: A => B): This[B]
268303
}
269304
trait FunctorCommon extends TypeClassCommon1 {
270305
type Instance[X] <: Functor[X]
271306
def pure[A](x: A): This[A]
272307
}
273308
object Functor extends TypeClassCompanion1 {
274-
type Impl[T[_]] = Extension1[T] with FunctorCommon
309+
type Impl[T[_]] = FunctorCommon { type This = T }
275310
}
276311

277312
trait Monad[A] extends Functor[A] {
278-
val common: MonadCommon
279-
import common._
313+
val commons: MonadCommon
314+
import commons._
280315
def flatMap[B](f: A => This[B]): This[B]
281-
def map[B](f: A => B) = this.flatMap(f.andThen(common.pure))
316+
def map[B](f: A => B) = this.flatMap(f.andThen(commons.pure))
282317
}
283318
trait MonadCommon extends FunctorCommon {
284319
type Instance[X] <: Monad[X]
285320
}
286321
object Monad extends TypeClassCompanion1 {
287-
type Impl[T[_]] = Extension1[T] with MonadCommon
322+
type Impl[T[_]] = MonadCommon { type This = T }
288323
}
289324

290325
def develop[A, F[X]](n: Int, x: A, f: A => A)(implicit ev: Functor.Impl[F]): F[A] =
291326
if (n == 0) Functor.impl[F].pure(x)
292327
else develop(n - 1, x, f).map(f)
293328

294-
implicit object ListMonad extends Extension1[List] with MonadCommon {
295-
type This[A] = List[A]
329+
implicit object ListMonad extends MonadCommon {
330+
type This = List
296331
type Instance = Monad
297332
def pure[A](x: A) = x :: Nil
298333
def inject[A]($this: List[A]) = new Monad[A] {
299-
val common: ListMonad.this.type = ListMonad
334+
val commons: ListMonad.this.type = ListMonad
335+
import commons._
300336
def flatMap[B](f: A => List[B]): List[B] = $this.flatMap(f)
301337
}
302338
}
303339

304340
object MonadFlatten {
305-
def flatten[T[_], A]($this: T[T[A]])(implicit ev: Monad.Impl[T]): T[A] =
341+
def flattened[T[_], A]($this: T[T[A]])(implicit ev: Monad.Impl[T]): T[A] =
306342
$this.flatMap(identity )
307343
}
344+
345+
MonadFlatten.flattened(List(List(1, 2, 3), List(4, 5)))
308346
}

0 commit comments

Comments
 (0)