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