-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
FunctionInstances.scala
212 lines (164 loc) · 7.84 KB
/
FunctionInstances.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/*
* Copyright (c) 2015 Typelevel
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package cats.kernel
package instances
import cats.kernel.compat.scalaVersionSpecific._
import scala.util.control.TailCalls.{done, tailcall, TailRec}
@suppressUnusedImportWarningForScalaVersionSpecific
trait FunctionInstances extends FunctionInstances0 {
implicit def catsKernelOrderForFunction0[A](implicit ev: Order[A]): Order[() => A] =
Order.by(_.apply())
implicit def catsKernelCommutativeGroupForFunction0[A](implicit G: CommutativeGroup[A]): CommutativeGroup[() => A] =
new Function0Group[A] with CommutativeGroup[() => A] { def A: Group[A] = G }
implicit def catsKernelCommutativeGroupForFunction1[A, B](implicit G: CommutativeGroup[B]): CommutativeGroup[A => B] =
new Function1Group[A, B] with CommutativeGroup[A => B] { def B: Group[B] = G }
}
private[instances] trait FunctionInstances0 extends FunctionInstances1 {
implicit def catsKernelHashForFunction0[A](implicit ev: Hash[A]): Hash[() => A] =
new Hash[() => A] {
def hash(x: () => A) = ev.hash(x())
def eqv(x: () => A, y: () => A) = ev.eqv(x(), y())
}
implicit def catsKernelPartialOrderForFunction0[A](implicit ev: PartialOrder[A]): PartialOrder[() => A] =
PartialOrder.by(_.apply())
implicit def catsKernelGroupForFunction0[A](implicit G: Group[A]): Group[() => A] =
new Function0Group[A] { def A: Group[A] = G }
implicit def catsKernelGroupForFunction1[A, B](implicit G: Group[B]): Group[A => B] =
new Function1Group[A, B] { def B: Group[B] = G }
implicit def catsKernelBoundedSemilatticeForFunction0[A](implicit
G: BoundedSemilattice[A]
): BoundedSemilattice[() => A] =
new Function0Monoid[A] with BoundedSemilattice[() => A] { def A: Monoid[A] = G }
implicit def catsKernelBoundedSemilatticeForFunction1[A, B](implicit
G: BoundedSemilattice[B]
): BoundedSemilattice[A => B] =
new Function1Monoid[A, B] with BoundedSemilattice[A => B] { def B: Monoid[B] = G }
}
private[instances] trait FunctionInstances1 extends FunctionInstances2 {
implicit def catsKernelEqForFunction0[A](implicit ev: Eq[A]): Eq[() => A] =
Eq.by(_.apply())
implicit def catsKernelCommutativeMonoidForFunction0[A](implicit
M: CommutativeMonoid[A]
): CommutativeMonoid[() => A] =
new Function0Monoid[A] with CommutativeMonoid[() => A] { def A: Monoid[A] = M }
implicit def catsKernelCommutativeMonoidForFunction1[A, B](implicit
M: CommutativeMonoid[B]
): CommutativeMonoid[A => B] =
new Function1Monoid[A, B] with CommutativeMonoid[A => B] { def B: Monoid[B] = M }
implicit def catsKernelSemilatticeForFunction0[A](implicit M: Semilattice[A]): Semilattice[() => A] =
new Function0Semigroup[A] with Semilattice[() => A] { def A: Semigroup[A] = M }
implicit def catsKernelSemilatticeForFunction1[A, B](implicit M: Semilattice[B]): Semilattice[A => B] =
new Function1Semigroup[A, B] with Semilattice[A => B] { def B: Semigroup[B] = M }
}
private[instances] trait FunctionInstances2 extends FunctionInstances3 {
implicit def catsKernelMonoidForFunction0[A](implicit M: Monoid[A]): Monoid[() => A] =
new Function0Monoid[A] { def A: Monoid[A] = M }
implicit def catsKernelMonoidForFunction1[A, B](implicit M: Monoid[B]): Monoid[A => B] =
new Function1Monoid[A, B] { def B: Monoid[B] = M }
implicit def catsKernelBandForFunction0[A](implicit S: Band[A]): Band[() => A] =
new Function0Semigroup[A] with Band[() => A] { def A: Semigroup[A] = S }
implicit def catsKernelBandForFunction1[A, B](implicit S: Band[B]): Band[A => B] =
new Function1Semigroup[A, B] with Band[A => B] { def B: Semigroup[B] = S }
}
private[instances] trait FunctionInstances3 extends FunctionInstances4 {
implicit def catsKernelCommutativeSemigroupForFunction0[A](implicit
S: CommutativeSemigroup[A]
): CommutativeSemigroup[() => A] =
new Function0Semigroup[A] with CommutativeSemigroup[() => A] { def A: Semigroup[A] = S }
implicit def catsKernelCommutativeSemigroupForFunction1[A, B](implicit
S: CommutativeSemigroup[B]
): CommutativeSemigroup[A => B] =
new Function1Semigroup[A, B] with CommutativeSemigroup[A => B] { def B: Semigroup[B] = S }
}
private[instances] trait FunctionInstances4 {
implicit def catsKernelSemigroupForFunction0[A](implicit S: Semigroup[A]): Semigroup[() => A] =
new Function0Semigroup[A] { def A: Semigroup[A] = S }
implicit def catsKernelSemigroupForFunction1[A, B](implicit S: Semigroup[B]): Semigroup[A => B] =
new Function1Semigroup[A, B] { def B: Semigroup[B] = S }
}
final private[instances] case class CombineFunction1[A, B](left: A => B, right: A => B, semiB: Semigroup[B])
extends (A => B) {
private def call(fn: A => B, a: A): TailRec[B] =
fn match {
case ref: CombineFunction1[A, B] @unchecked =>
for {
lb <- tailcall(call(ref.left, a))
rb <- tailcall(call(ref.right, a))
} yield ref.semiB.combine(lb, rb)
case _ => done(fn(a))
}
final override def apply(a: A): B = call(this, a).result
}
trait Function1Semigroup[A, B] extends Semigroup[A => B] {
implicit def B: Semigroup[B]
override def combine(x: A => B, y: A => B): A => B =
CombineFunction1(x, y, B)
override def combineAllOption(fns: IterableOnce[A => B]): Option[A => B] =
if (fns.iterator.isEmpty) None
else
Some { (a: A) =>
B.combineAllOption(fns.iterator.map(_.apply(a))).get
}
}
trait Function1Monoid[A, B] extends Function1Semigroup[A, B] with Monoid[A => B] {
implicit def B: Monoid[B]
val empty: A => B =
(_: A) => B.empty
}
trait Function1Group[A, B] extends Function1Monoid[A, B] with Group[A => B] {
implicit def B: Group[B]
def inverse(x: A => B): A => B =
(a: A) => B.inverse(x(a))
}
final private[instances] case class CombineFunction0[A](left: () => A, right: () => A, semiA: Semigroup[A])
extends (() => A) {
private def call(fn: () => A): TailRec[A] =
fn match {
case ref: CombineFunction0[A] @unchecked =>
for {
la <- tailcall(call(ref.left))
ra <- tailcall(call(ref.right))
} yield ref.semiA.combine(la, ra)
case _ => done(fn())
}
final override def apply(): A = call(this).result
}
trait Function0Semigroup[A] extends Semigroup[() => A] {
implicit def A: Semigroup[A]
override def combine(x: () => A, y: () => A): () => A =
CombineFunction0(x, y, A)
override def combineAllOption(fns: IterableOnce[() => A]): Option[() => A] =
if (fns.iterator.isEmpty) None
else
Some { () =>
A.combineAllOption(fns.iterator.map(_.apply())).get
}
}
trait Function0Monoid[A] extends Function0Semigroup[A] with Monoid[() => A] {
implicit def A: Monoid[A]
val empty: () => A =
() => A.empty
}
trait Function0Group[A] extends Function0Monoid[A] with Group[() => A] {
implicit def A: Group[A]
def inverse(x: () => A): () => A =
() => A.inverse(x())
}