1
+ package object groups {
2
+ trait Semigroup [A ] {
3
+ def combine (x : A , y : A ): A
4
+ }
5
+
6
+ object Semigroup {
7
+ def instance [A ](f : (A , A ) => A ): Semigroup [A ] =
8
+ new Semigroup [A ] {
9
+ def combine (x : A , y : A ): A = f(x, y)
10
+ }
11
+ }
12
+
13
+ type Id [A ] = A
14
+
15
+ trait Wrapping [F [_]] {
16
+ def wraps [G [_], A ](ga : G [A ]): G [F [A ]]
17
+ def unwrap [G [_], A ](ga : G [F [A ]]): G [A ]
18
+ }
19
+
20
+ abstract class Wrapper { self =>
21
+ type F [_]
22
+ def wraps [G [_], A ](ga : G [A ]): G [F [A ]]
23
+ def unwrap [G [_], A ](gfa : G [F [A ]]): G [A ]
24
+
25
+ final def apply [A ](a : A ): F [A ] = wraps[Id , A ](a)
26
+
27
+ implicit object WrapperWrapping extends Wrapping [F ] {
28
+ def wraps [G [_], A ](ga : G [A ]): G [F [A ]] = self.wraps(ga)
29
+ def unwrap [G [_], A ](ga : G [F [A ]]): G [A ] = self.unwrap(ga)
30
+ }
31
+ }
32
+
33
+ opaque type First [A ] = A
34
+ object First extends Wrapper {
35
+ type F = First
36
+ def wraps [G [_], A ](ga : G [A ]): G [First [A ]] = ga
37
+ def unwrap [G [_], A ](gfa : G [First [A ]]): G [A ] = gfa
38
+ implicit def firstSemigroup [A ]: Semigroup [First [A ]] =
39
+ Semigroup .instance((x, y) => x)
40
+ }
41
+
42
+ opaque type Last [A ] = A
43
+ object Last extends Wrapper {
44
+ type F = Last
45
+ def wraps [G [_], A ](ga : G [A ]): G [Last [A ]] = ga
46
+ def unwrap [G [_], A ](gfa : G [Last [A ]]): G [A ] = gfa
47
+ implicit def lastSemigroup [A ]: Semigroup [Last [A ]] =
48
+ Semigroup .instance((x, y) => y)
49
+ }
50
+
51
+ opaque type Min [A ] = A
52
+ object Min extends Wrapper {
53
+ type F = Min
54
+ def wraps [G [_], A ](ga : G [A ]): G [Min [A ]] = ga
55
+ def unwrap [G [_], A ](gfa : G [Min [A ]]): G [A ] = gfa
56
+ implicit def minSemigroup [A ](implicit o : Ordering [A ]): Semigroup [Min [A ]] =
57
+ Semigroup .instance(o.min)
58
+ }
59
+
60
+ opaque type Max [A ] = A
61
+ object Max extends Wrapper {
62
+ type F = Max
63
+ def wraps [G [_], A ](ga : G [A ]): G [Max [A ]] = ga
64
+ def unwrap [G [_], A ](gfa : G [Max [A ]]): G [A ] = gfa
65
+ implicit def maxSemigroup [A ](implicit o : Ordering [A ]): Semigroup [Max [A ]] =
66
+ Semigroup .instance(o.max)
67
+ }
68
+
69
+ opaque type Plus [A ] = A
70
+ object Plus extends Wrapper {
71
+ type F = Plus
72
+ def wraps [G [_], A ](ga : G [A ]): G [Plus [A ]] = ga
73
+ def unwrap [G [_], A ](gfa : G [Plus [A ]]): G [A ] = gfa
74
+ implicit def plusSemigroup [A ](implicit n : Numeric [A ]): Semigroup [Plus [A ]] =
75
+ Semigroup .instance(n.plus)
76
+ }
77
+
78
+ opaque type Times [A ] = A
79
+ object Times extends Wrapper {
80
+ type F = Times
81
+ def wraps [G [_], A ](ga : G [A ]): G [Times [A ]] = ga
82
+ def unwrap [G [_], A ](gfa : G [Times [A ]]): G [A ] = gfa
83
+ implicit def timesSemigroup [A ](implicit n : Numeric [A ]): Semigroup [Times [A ]] =
84
+ Semigroup .instance(n.times)
85
+ }
86
+
87
+ opaque type Reversed [A ] = A
88
+ object Reversed extends Wrapper {
89
+ type F = Reversed
90
+ def wraps [G [_], A ](ga : G [A ]): G [Reversed [A ]] = ga
91
+ def unwrap [G [_], A ](gfa : G [Reversed [A ]]): G [A ] = gfa
92
+ implicit def reversedOrdering [A ](implicit o : Ordering [A ]): Ordering [Reversed [A ]] =
93
+ o.reverse
94
+ }
95
+
96
+ opaque type Unordered [A ] = A
97
+ object Unordered extends Wrapper {
98
+ type F = Unordered
99
+ def wraps [G [_], A ](ga : G [A ]): G [Unordered [A ]] = ga
100
+ def unwrap [G [_], A ](gfa : G [Unordered [A ]]): G [A ] = gfa
101
+ implicit def unorderedOrdering [A ]: Ordering [Unordered [A ]] =
102
+ Ordering .by(_ => ())
103
+ }
104
+ }
0 commit comments