1
1
/** A possible type class encoding for
2
2
3
- trait SemiGroup {
4
- def add(that: This): This
5
- }
6
-
7
- trait Monoid extends SemiGroup
8
- common {
9
- def unit: This
10
- }
3
+ trait SemiGroup extends TypeClass {
4
+ def add(that: This): This
5
+ }
11
6
12
- extension IntOps for Int : Monoid {
13
- def add(that: Int) = this + that
14
- }
15
- common {
16
- def unit = 0
17
- }
7
+ trait Monoid extends SemiGroup
8
+ common {
9
+ def unit: This
10
+ }
18
11
19
- extension StringOps for String : Monoid {
20
- def add(that: Int) = this + + that
21
- }
22
- common {
23
- def unit = ""
24
- }
12
+ extension IntOps for Int : Monoid {
13
+ def add(that: Int) = this + that
14
+ }
15
+ common {
16
+ def unit = 0
17
+ }
25
18
26
- def sum[T: Monoid](xs: List[T]): T =
27
- (instance[T, Monoid].unit /: xs)(_ `add` _)
19
+ extension StringOps for String : Monoid {
20
+ def add(that: Int) = this ++ that
21
+ }
22
+ common {
23
+ def unit = ""
24
+ }
28
25
26
+ def sum[T: Monoid](xs: List[T]): T =
27
+ (Monod.impl[T].unit /: xs)(_ `add` _)
29
28
*/
30
29
object runtime {
31
30
@@ -40,6 +39,11 @@ object runtime {
40
39
def inject (x : This ): Instance { val common : self.type }
41
40
}
42
41
42
+ trait TypeClassCompanion {
43
+ type Impl [T ] <: Extension [T , _]
44
+ def impl [T ](implicit ev : Impl [T ]): Impl [T ] = ev
45
+ }
46
+
43
47
trait Extension [From , To <: TypeClass ] extends TypeClassCommon {
44
48
type This = From
45
49
type Instance = To
@@ -54,12 +58,16 @@ import runtime._
54
58
object semiGroups {
55
59
56
60
trait SemiGroup extends TypeClass {
61
+ val common : SemiGroupCommon
57
62
import common ._
58
63
def add (that : This ): This
59
64
}
60
65
trait SemiGroupCommon extends TypeClassCommon {
61
66
type Instance <: SemiGroup
62
67
}
68
+ object SemiGroup extends TypeClassCompanion {
69
+ type Impl [T ] = Extension [T , SemiGroup ] with SemiGroupCommon
70
+ }
63
71
64
72
trait Monoid extends SemiGroup {
65
73
val common : MonoidCommon
@@ -69,6 +77,9 @@ object semiGroups {
69
77
type Instance <: Monoid
70
78
def unit : This
71
79
}
80
+ object Monoid extends TypeClassCompanion {
81
+ type Impl [T ] = Extension [T , Monoid ] with MonoidCommon
82
+ }
72
83
73
84
implicit object IntOps extends Extension [Int , Monoid ] with MonoidCommon { self =>
74
85
type This = Int
@@ -90,51 +101,51 @@ object semiGroups {
90
101
}
91
102
}
92
103
93
- def sum [T ](xs : List [T ])(implicit $ev : Extension [ T , Monoid ] with MonoidCommon ) =
94
- (implicitly[ Extension [ T , Monoid ] with MonoidCommon ].unit /: xs)((x, y) => x `add` y)
104
+ def sum [T ](xs : List [T ])(implicit $ev : Monoid . Impl [ T ] ) =
105
+ (Monoid .impl[ T ].unit /: xs)((x, y) => x `add` y)
95
106
}
96
107
97
108
/** Encoding for
98
109
99
- trait Ord {
100
- def compareTo(that: This): Int
101
- def < (that: This) = compareTo(that) < 0
102
- def > (that: This) = compareTo(that) > 0
103
- }
104
- common {
105
- val minimum: This
106
- }
110
+ trait Ord extends TypeClass {
111
+ def compareTo(that: This): Int
112
+ def < (that: This) = compareTo(that) < 0
113
+ def > (that: This) = compareTo(that) > 0
114
+ }
115
+ common {
116
+ val minimum: This
117
+ }
107
118
108
- extension IntOrd for Int : Ord {
109
- def compareTo(that: Int) =
110
- if (this < that) -1 else if (this > that) +1 else 0
111
- }
112
- common {
113
- val minimum = Int.MinValue
114
- }
119
+ extension IntOrd for Int : Ord {
120
+ def compareTo(that: Int) =
121
+ if (this < that) -1 else if (this > that) +1 else 0
122
+ }
123
+ common {
124
+ val minimum = Int.MinValue
125
+ }
115
126
116
- extension ListOrd[T : Ord] for List[T] : Ord {
117
- def compareTo(that: List[T]): Int = (this, that) match {
118
- case (Nil, Nil) => 0
119
- case (Nil, _) => -1
120
- case (_, Nil) => +1
121
- case (x :: xs, y :: ys) =>
122
- val fst = x.compareTo(y)
123
- if (fst != 0) fst else xs.compareTo(ys)
127
+ extension ListOrd[T : Ord] for List[T] : Ord {
128
+ def compareTo(that: List[T]): Int = (this, that) match {
129
+ case (Nil, Nil) => 0
130
+ case (Nil, _) => -1
131
+ case (_, Nil) => +1
132
+ case (x :: xs, y :: ys) =>
133
+ val fst = x.compareTo(y)
134
+ if (fst != 0) fst else xs.compareTo(ys)
135
+ }
136
+ }
137
+ common {
138
+ val minimum = Nil
124
139
}
125
- }
126
- common {
127
- val minimum = Nil
128
- }
129
140
130
- def min[T: Ord](x: T, y: T) = if (x < y) x else y
141
+ def min[T: Ord](x: T, y: T) = if (x < y) x else y
131
142
132
- def inf[T: Ord](xs: List[T]): T = (instance[T, Ord ].minimum /: xs)(_ ` min` _ )
143
+ def inf[T: Ord](xs: List[T]): T = (Ord.impl[T ].minimum /: xs)(min)
133
144
*/
134
-
135
145
object ord {
136
146
137
147
trait Ord extends TypeClass {
148
+ val common : OrdCommon
138
149
import common ._
139
150
def compareTo (that : This ): Int
140
151
def < (that : This ) = compareTo(that) < 0
@@ -144,6 +155,9 @@ object ord {
144
155
type Instance <: Ord
145
156
def minimum : This
146
157
}
158
+ object Ord extends TypeClassCompanion {
159
+ type Impl [T ] = Extension [T , Ord ] with OrdCommon
160
+ }
147
161
148
162
implicit object IntOrd extends Extension [Int , Ord ] with OrdCommon { self =>
149
163
type This = Int
@@ -156,7 +170,7 @@ object ord {
156
170
}
157
171
}
158
172
159
- class ListOrd [T ](implicit ev : Extension [ T , Ord ] with OrdCommon )
173
+ class ListOrd [T ](implicit ev : Ord . Impl [ T ] )
160
174
extends Extension [List [T ], Ord ] with OrdCommon { self =>
161
175
type This = List [T ]
162
176
type Instance = Ord
@@ -174,14 +188,123 @@ object ord {
174
188
}
175
189
}
176
190
177
- implicit def listOrd [T ](implicit ev : Extension [ T , Ord ] with OrdCommon ): ListOrd [T ] =
191
+ implicit def listOrd [T ](implicit ev : Ord . Impl [ T ] ): ListOrd [T ] =
178
192
new ListOrd [T ]
179
193
180
- def min [T ](x : T , y : T )(implicit ev : Extension [ T , Ord ] with OrdCommon ): T =
194
+ def min [T ](x : T , y : T )(implicit ev : Ord . Impl [ T ] ): T =
181
195
if (x < y) x else y
182
196
183
- def inf [T ](xs : List [T ])(implicit ev : Extension [T , Ord ] with OrdCommon ): T = {
184
- val smallest = implicitly[Extension [T , Ord ] with OrdCommon ].minimum
185
- (smallest /: xs)(min(_, _))
197
+ def inf [T ](xs : List [T ])(implicit ev : Ord .Impl [T ]): T = {
198
+ val smallest = Ord .impl[T ].minimum
199
+ (smallest /: xs)(min)
200
+ }
201
+ }
202
+
203
+ /** Encoding for
204
+
205
+ trait Functor[A] extends TypeClass1 {
206
+ def map[B](f: A => B): This[B]
207
+ }
208
+ common {
209
+ def pure[A](x: A): This[A]
210
+ }
211
+
212
+ // Generically, `pure[A]{.map(f)}^n`
213
+ def develop[A, F[X] : Functor[X]](n: Int, f: A => A): F[A] =
214
+ if (n == 0) Functor.impl[F].pure[A]
215
+ else develop[A, F](n - 1, f).map(f)
216
+
217
+ trait Monad[A] extends Functor[A] {
218
+ def flatMap[B](f: A => This[B]): This[B]
219
+ def map[B](f: A => B) = this.flatMap(f.andThen(pure))
220
+ }
221
+
222
+ extension ListMonad[T] for List[T] : Monad[T] {
223
+ static def pure[A] = Nil
224
+
225
+ def flatMap[B](f: A => List[B]): List[B] = this match {
226
+ case x :: xs => f(x) ++ xs.flatMap(f)
227
+ case Nil => Nil
228
+ }
229
+ }
230
+
231
+ extension MonadFlatten[T[X]: Monad[X]] for T[T[A]] {
232
+ def flatten: T[A] = this.flatMap(identity)
233
+ }
234
+ */
235
+ object runtime1 {
236
+
237
+ trait TypeClass1 {
238
+ val common : TypeClassCommon1
239
+ type This = common.This
240
+ }
241
+
242
+ trait TypeClassCommon1 { self =>
243
+ type This [X ]
244
+ type Instance [X ] <: TypeClass1
245
+ def inject [A ](x : This [A ]): Instance [A ] { val common : self.type }
246
+ }
247
+
248
+ trait TypeClassCompanion1 {
249
+ type Impl [T [_]] <: Extension1 [T , _]
250
+ def impl [T [_]](implicit ev : Impl [T ]): Impl [T ] = ev
251
+ }
252
+
253
+ trait Extension1 [From [_], To [X ] <: TypeClass1 ] extends TypeClassCommon1 {
254
+ type This [X ] = From [X ]
255
+ type Instance [X ] = To [X ]
256
+ }
257
+
258
+ implicit def inject1 [A , From [_]](x : From [A ])
259
+ (implicit ev : Extension1 [From , _]): ev.Instance [A ] { type This = From } =
260
+ ev.inject(x)
261
+ }
262
+ import runtime1 ._
263
+
264
+ object functors {
265
+
266
+ trait Functor [A ] extends TypeClass1 {
267
+ val common : FunctorCommon
268
+ import common ._
269
+ def map [B ](f : A => B ): This [B ]
270
+ }
271
+ trait FunctorCommon extends TypeClassCommon1 {
272
+ type Instance [X ] <: Functor [X ]
273
+ def pure [A ](x : A ): This [A ]
274
+ }
275
+ object Functor extends TypeClassCompanion1 {
276
+ type Impl [T [_]] = Extension1 [T , Functor ] with FunctorCommon
277
+ }
278
+
279
+ trait Monad [A ] extends Functor [A ] {
280
+ val common : MonadCommon
281
+ import common ._
282
+ def flatMap [B ](f : A => This [B ]): This [B ]
283
+ def map [B ](f : A => B ) = this .flatMap(f.andThen(common.pure))
284
+ }
285
+ trait MonadCommon extends FunctorCommon {
286
+ type Instance [X ] <: Monad [X ]
287
+ }
288
+ object Monad extends TypeClassCompanion1 {
289
+ type Impl [T [_]] = Extension1 [T , Monad ] with MonadCommon
290
+ }
291
+
292
+ def develop [A , F [X ]](n : Int , x : A , f : A => A )(implicit ev : Functor .Impl [F ]): F [A ] =
293
+ if (n == 0 ) Functor .impl[F ].pure(x)
294
+ else develop(n - 1 , x, f).map(f)
295
+
296
+ implicit object ListMonad extends Extension1 [List , Monad ] with MonadCommon { self =>
297
+ type This [A ] = List [A ]
298
+ type Instance = Monad
299
+ def pure [A ](x : A ) = x :: Nil
300
+ def inject [A ]($this : List [A ]) = new Monad [A ] {
301
+ val common : self.type = self
302
+ def flatMap [B ](f : A => List [B ]): List [B ] = $this .flatMap(f)
303
+ }
304
+ }
305
+
306
+ object MonadFlatten {
307
+ def flatten [T [_], A ]($this : T [T [A ]])(implicit ev : Monad .Impl [T ]): T [A ] =
308
+ $this .flatMap(identity )
186
309
}
187
310
}
0 commit comments