1
1
/*
2
2
[T : M] = [T] ... (implicit ev: Injectable[T, M]) if M is a normal trait
3
- = [T] ... (implicit ev: M.Impl[T]) if M is an extension trait
3
+ = [T] ... (implicit ev: M.Impl[T]) if M is a trait with common members
4
4
5
5
M.Impl[T] = Common { type This = T }
6
6
M.Impl[T[_]] = Common { type This = T }
7
7
...
8
8
9
- Extension traits of different kinds cannot be mixed.
10
- Extension traits can extend normal traits.
11
- Extension traits can extend extension traits, but only with the same type parameters
12
- Normal traits cannot extend extension traits.
9
+ - An extension trait is a trait that uses This or a trait inheriting an extension trait.
10
+ - The kind of `This` is the kind of the extension trait.
11
+ - Extension traits of different kinds cannot inherit each other and cannot be mixed using `with`.
12
+ - A class implementing extension traits fixes the maning of `This`.
13
+ - Such a class cannot be extended by classes that implement other extension traits.
13
14
*/
14
15
object runtime {
15
16
16
- trait TypeClass {
17
- /** The companion object of the implementing type */
18
- val `common` : TypeClass .Common
19
- }
20
-
21
17
trait Injector {
18
+ /** The implementating type */
22
19
type This
20
+
21
+ /** The implemented trait */
23
22
type Instance
23
+
24
+ /** The implementation via type `T` for this trait */
24
25
implicit def inject (x : This ): Instance
25
26
}
26
27
28
+ trait IdentityInjector extends Injector {
29
+ def inject (x : This ): Instance = x.asInstanceOf
30
+ }
31
+
32
+ trait SubtypeInjector [T ] extends Injector {
33
+ type This = T
34
+ type Instance = T
35
+ def inject (x : T ): T = x
36
+ }
37
+
27
38
type Injectable [T , + U ] = Injector { type This = T ; type Instance <: U }
28
39
29
- implicit def selfInject [U , T <: U ]: Injectable [T , U ] =
30
- new Injector {
31
- type This = T
32
- type Instance = U
33
- implicit def inject ( x : This ) : Instance = x
34
- }
40
+ def selfInject [U , T <: U ]: Injectable [T , U ] = new SubtypeInjector [ T ] {}
41
+
42
+ trait TypeClass {
43
+ /** The companion object of the implementing type */
44
+ val `common` : TypeClass . Common
45
+ }
35
46
36
47
object TypeClass {
37
48
38
49
/** Base trait for companion objects of all implementations of this typeclass */
39
50
trait Common extends Injector { self =>
40
-
41
- /** The implementating type */
42
- type This
43
-
44
51
/** The implemented typeclass */
45
- type Instance <: TypeClass { val `common` : self.type }
46
-
47
- /** Create instances of typeclass from instances of the implementing type */
48
- implicit def inject (x : This ): Instance
52
+ type Instance <: TypeClass
49
53
}
50
54
51
55
/** Base trait for the companion objects of type classes themselves */
52
56
trait Companion {
53
-
54
57
/** The `Common` base trait defining common (static) operations of this typeclass */
55
58
type Common <: TypeClass .Common
56
59
@@ -62,9 +65,8 @@ object runtime {
62
65
}
63
66
}
64
67
65
- implicit def injectTypeClass [From , U ](x : From )
66
- (implicit ev : Injector { type This = From }): ev.Instance =
67
- ev.inject(x)
68
+ implicit def applyInjector [From , U ](x : From )(implicit ev : Injector { type This = From }): ev.Instance =
69
+ ev.inject(x)
68
70
}
69
71
70
72
/** 0. All combinations of
@@ -235,13 +237,14 @@ object hasLength {
235
237
def length : Int
236
238
}
237
239
238
- trait HasBoundedLength extends HasLength {
240
+ trait HasBoundedLength extends HasLength with TypeClass {
239
241
val `common` : HasBoundedLength .Common
240
242
import `common` ._
241
243
}
242
244
243
- object HasBoundedLength {
244
- trait Common {
245
+ object HasBoundedLength extends TypeClass .Companion {
246
+ trait Common extends TypeClass .Common {
247
+ type Instance <: HasBoundedLength
245
248
def limit : Int
246
249
}
247
250
}
@@ -252,7 +255,7 @@ object hasLength {
252
255
}
253
256
254
257
object HasBoundedLengthX extends TypeClass .Companion {
255
- trait Common extends HasBoundedLength .Common with TypeClass .Common { self =>
258
+ trait Common extends HasBoundedLength .Common with TypeClass .Common { self =>
256
259
type Instance <: HasBoundedLengthX { val `common` : self.type }
257
260
def limit : Int
258
261
def longest : This
@@ -271,50 +274,46 @@ object hasLength {
271
274
val `common` : C2Common = C2
272
275
import `common` ._
273
276
}
274
- class C2Common extends HasBoundedLength .Common {
277
+ abstract class C2Common extends HasBoundedLength .Common {
275
278
def limit = 100
276
279
}
277
- object C2 extends C2Common
280
+ object C2 extends C2Common with SubtypeInjector [ C2 ]
278
281
279
282
class CG2 [T ](xs : Array [T ]) extends CG1 (xs) with HasBoundedLength {
280
283
val `common` : CG2Common [T ] = CG2 [T ]
281
284
import `common` ._
282
285
}
283
- class CG2Common [T ] extends HasBoundedLength .Common {
286
+ abstract class CG2Common [T ] extends HasBoundedLength .Common {
284
287
def limit = 100
285
288
}
286
289
object CG2 {
287
- def apply [T ] = new CG2Common [T ]
290
+ def apply [T ] = new CG2Common [T ] with SubtypeInjector [ CG2 [ T ]]
288
291
}
289
292
290
293
class C3 (xs : Array [Int ]) extends C2 (xs) with HasBoundedLengthX {
291
294
override val `common` : C3Common = C3
292
295
import `common` ._
293
296
}
294
- class C3Common extends C2Common with HasBoundedLengthX .Common { self =>
297
+ abstract class C3Common extends C2Common with HasBoundedLengthX .Common { self =>
295
298
type This = C3
296
299
type Instance = C3 { val `common` : self.type }
297
- def inject (x : This ): Instance = x.asInstanceOf
298
300
299
301
def longest = new C3 (new Array [Int ](limit))
300
302
}
301
- implicit object C3 extends C3Common
303
+ object C3 extends C3Common with IdentityInjector
302
304
303
305
class CG3 [T ](xs : Array [T ])(implicit tag : ClassTag [T ]) extends CG2 (xs) with HasBoundedLengthX {
304
306
override val `common` : CG3Common [T ] = CG3 [T ]
305
307
import `common` ._
306
308
}
307
- class CG3Common [T ](implicit tag : ClassTag [T ]) extends CG2Common [T ] with HasBoundedLengthX .Common { self =>
309
+ abstract class CG3Common [T ](implicit tag : ClassTag [T ]) extends CG2Common [T ] with HasBoundedLengthX .Common { self =>
308
310
type This = CG3 [T ]
309
311
type Instance = CG3 [T ] { val `common` : self.type }
310
- def inject (x : This ): Instance = x.asInstanceOf
311
-
312
312
def longest = new CG3 (new Array [T ](limit))
313
313
}
314
314
object CG3 {
315
- def apply [T ](implicit tag : ClassTag [T ]) = new CG3Common [T ]
315
+ def apply [T ](implicit tag : ClassTag [T ]) = new CG3Common [T ] with IdentityInjector
316
316
}
317
- implicit def CG3Common [T ](implicit tag : ClassTag [T ]): CG3Common [T ] = CG3 [T ]
318
317
319
318
class D1 (val xs : Array [Int ])
320
319
class DG1 [T ](val xs : Array [T ])
@@ -342,7 +341,7 @@ object hasLength {
342
341
}
343
342
implicit def DGHasLength [T ]: DGHasLength [T ] = new DGHasLength
344
343
345
- implicit object DHasBoundedLength extends Injector with HasBoundedLength .Common { self =>
344
+ object DHasBoundedLength extends HasBoundedLength .Common { self =>
346
345
type This = D2
347
346
type Instance = HasBoundedLength
348
347
def inject (x : D2 ) = new HasBoundedLength {
@@ -353,7 +352,7 @@ object hasLength {
353
352
def limit = 100
354
353
}
355
354
356
- class DGHasBoundedLength [T ] extends Injector with HasBoundedLength .Common { self =>
355
+ class DGHasBoundedLength [T ] extends HasBoundedLength .Common { self =>
357
356
type This = DG2 [T ]
358
357
type Instance = HasBoundedLength
359
358
def inject (x : DG2 [T ]) = new HasBoundedLength {
@@ -395,8 +394,8 @@ object hasLength {
395
394
def lengthOK [T ](x : T )(implicit ev : Injectable [T , HasBoundedLength ]) =
396
395
x.length < x.common.limit
397
396
398
- def lengthOKX [T ](x : T )(implicit ev : HasBoundedLengthX .Impl [T ]) =
399
- x.length < HasBoundedLengthX .impl[T ].limit
397
+ def lengthOKX [T ](x : T )(implicit ev : HasBoundedLength .Impl [T ]) =
398
+ x.length < HasBoundedLength .impl[T ].limit
400
399
401
400
def longestLengthOK [T ](implicit ev : HasBoundedLengthX .Impl [T ], tag : ClassTag [T ]) = {
402
401
val impl = HasBoundedLengthX .impl[T ]
@@ -406,7 +405,11 @@ object hasLength {
406
405
def length1 (x : HasLength ) = x.length
407
406
def lengthOK1 (x : HasBoundedLength ) = x.length < x.common.limit
408
407
408
+ def ctag [T ](implicit tag : ClassTag [T ]) = tag
409
+
409
410
val xs = Array (1 , 2 , 3 )
411
+ val intTag = implicitly[ClassTag [Int ]]
412
+
410
413
val c1 = new C1 (xs)
411
414
val cg1 = new CG1 (xs)
412
415
val c2 = new C2 (xs)
@@ -421,38 +424,38 @@ object hasLength {
421
424
val d3 = new D3 (xs)
422
425
val dg3 = new DG3 (xs)
423
426
424
- length(c1)
425
- length(cg1)
426
- length(c2)
427
- length(cg2)
428
- length(c3)(selfInject )
429
- length(cg3)(selfInject )
430
-
431
- length(d1)
432
- length(dg1)
433
- length(d2)
434
- length(dg2)
435
- length(d3)
436
- length(dg3)
437
-
438
- lengthOK(c2)
439
- lengthOK(cg2)
440
- lengthOK(c3)(selfInject )
441
- lengthOK(cg3)(selfInject )
442
-
443
- lengthOK(d2)
444
- lengthOK(dg2)
445
- lengthOK(d3)
446
- lengthOK(dg3)
447
-
448
- lengthOKX(c3)
449
- lengthOKX(cg3)
450
-
451
- lengthOKX(d3)
452
- lengthOKX(dg3)
453
-
454
- longestLengthOK[C3 ]
455
- longestLengthOK[CG3 [Int ]]
427
+ length(c1)(selfInject)
428
+ length(cg1)(selfInject)
429
+ length(c2)( C2 )
430
+ length(cg2)( CG2 [ Int ])
431
+ length(c3)(C3 )
432
+ length(cg3)(CG3 [ Int ] )
433
+
434
+ length(d1)( DHasLength )
435
+ length(dg1)( DGHasLength [ Int ])
436
+ length(d2)( DHasBoundedLength )
437
+ length(dg2)( DGHasBoundedLength [ Int ])
438
+ length(d3)( DHasBoundedLengthX )
439
+ length(dg3)( DGHasBoundedLengthX [ Int ])
440
+
441
+ lengthOK(c2)( C2 )
442
+ lengthOK(cg2)( CG2 [ Int ])
443
+ lengthOK(c3)(C3 )
444
+ lengthOK(cg3)(CG3 [ Int ] )
445
+
446
+ lengthOK(d2)( DHasBoundedLength )
447
+ lengthOK(dg2)( DGHasBoundedLength [ Int ])
448
+ lengthOK(d3)( DHasBoundedLengthX )
449
+ lengthOK(dg3)( DGHasBoundedLengthX [ Int ])
450
+
451
+ lengthOKX(c3)( C3 )
452
+ lengthOKX(cg3)( CG3 [ Int ])
453
+
454
+ lengthOKX(d3)( DHasBoundedLengthX )
455
+ lengthOKX(dg3)( DGHasBoundedLengthX [ Int ])
456
+
457
+ longestLengthOK[C3 ]( C3 , ctag[ C3 ])
458
+ longestLengthOK[CG3 [Int ]]( CG3 [ Int ], ctag[ CG3 [ Int ]])
456
459
longestLengthOK[D3 ]
457
460
longestLengthOK[DG3 [Int ]]
458
461
@@ -716,7 +719,7 @@ object runtime1 {
716
719
object TypeClass1 {
717
720
trait Common { self =>
718
721
type This [X ]
719
- type Instance [X ] <: TypeClass1 [X ] { val `common` : self. type }
722
+ type Instance [X ] <: TypeClass1 [X ]
720
723
def inject [A ](x : This [A ]): Instance [A ]
721
724
}
722
725
@@ -727,7 +730,7 @@ object runtime1 {
727
730
}
728
731
}
729
732
730
- implicit def decorateTypeClass1 [A , From [_]](x : From [A ])
733
+ implicit def applyInjector1 [A , From [_]](x : From [A ])
731
734
(implicit ev : TypeClass1 .Common { type This = From }): ev.Instance [A ] =
732
735
ev.inject(x)
733
736
}
0 commit comments