Skip to content

Commit 68636bf

Browse files
committed
Add Lift{Value,Kind} instances for Resource
1 parent 1a43899 commit 68636bf

File tree

3 files changed

+123
-2
lines changed

3 files changed

+123
-2
lines changed

build.sbt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,8 @@ lazy val kernel = crossProject(JSPlatform, JVMPlatform, NativePlatform)
445445
.settings(
446446
name := "cats-effect-kernel",
447447
libraryDependencies ++= Seq(
448-
"org.typelevel" %%% "cats-core" % CatsVersion
448+
"org.typelevel" %%% "cats-core" % CatsVersion,
449+
"org.typelevel" %%% "cats-mtl" % CatsMtlVersion
449450
),
450451
mimaBinaryIssueFilters ++= Seq(
451452
ProblemFilters.exclude[MissingClassProblem]("cats.effect.kernel.Ref$SyncRef"),
@@ -501,7 +502,9 @@ lazy val laws = crossProject(JSPlatform, JVMPlatform, NativePlatform)
501502
name := "cats-effect-laws",
502503
libraryDependencies ++= Seq(
503504
"org.typelevel" %%% "cats-laws" % CatsVersion,
504-
"org.typelevel" %%% "discipline-munit" % DisciplineMUnitVersion % Test)
505+
"org.typelevel" %%% "cats-mtl-laws" % CatsMtlVersion % Test,
506+
"org.typelevel" %%% "discipline-munit" % DisciplineMUnitVersion % Test
507+
)
505508
)
506509

507510
/**

kernel/shared/src/main/scala/cats/effect/kernel/Resource.scala

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import cats.data.Kleisli
2121
import cats.effect.kernel.Resource.Pure
2222
import cats.effect.kernel.implicits._
2323
import cats.effect.kernel.instances.spawn
24+
import cats.mtl.{LiftKind, LiftValue}
2425
import cats.syntax.all._
2526

2627
import scala.annotation.tailrec
@@ -1275,6 +1276,10 @@ private[effect] trait ResourceHOInstances0 extends ResourceHOInstances1 {
12751276
def K = K0
12761277
def G = G0
12771278
}
1279+
1280+
implicit def catsEffectLiftKindForResource[F[_]](
1281+
implicit F: MonadCancel[F, ?]): LiftKind[F, Resource[F, *]] =
1282+
liftKindImpl(F)
12781283
}
12791284

12801285
private[effect] trait ResourceHOInstances1 extends ResourceHOInstances2 {
@@ -1289,6 +1294,25 @@ private[effect] trait ResourceHOInstances1 extends ResourceHOInstances2 {
12891294
def F = F0
12901295
def rootCancelScope = F0.rootCancelScope
12911296
}
1297+
1298+
protected[this] def liftKindImpl[F[_]](F: MonadCancel[F, ?]): LiftKind[F, Resource[F, *]] =
1299+
new LiftKind[F, Resource[F, *]] {
1300+
implicit val applicativeF: MonadCancel[F, ?] = F
1301+
val applicativeG: Applicative[Resource[F, *]] = catsEffectMonadForResource
1302+
def apply[A](fa: F[A]): Resource[F, A] = Resource.eval(fa)
1303+
def limitedMapK[A](ga: Resource[F, A])(scope: F ~> F): Resource[F, A] =
1304+
ga.mapK(scope)
1305+
}
1306+
1307+
implicit def catsEffectLiftKindForResourceComposed[F[_], G[_]](
1308+
implicit inner: LiftKind[F, G],
1309+
G: MonadCancel[G, ?]
1310+
): LiftKind[F, Resource[G, *]] =
1311+
inner.andThen(liftKindImpl(G))
1312+
1313+
implicit def catsEffectLiftValueForResource[F[_]](
1314+
implicit F: Applicative[F]): LiftValue[F, Resource[F, *]] =
1315+
liftValueImpl(F)
12921316
}
12931317

12941318
private[effect] trait ResourceHOInstances2 extends ResourceHOInstances3 {
@@ -1308,6 +1332,18 @@ private[effect] trait ResourceHOInstances2 extends ResourceHOInstances3 {
13081332

13091333
final implicit def catsEffectDeferForResource[F[_]]: Defer[Resource[F, *]] =
13101334
new ResourceDefer[F]
1335+
1336+
protected[this] def liftValueImpl[F[_]](F: Applicative[F]): LiftValue[F, Resource[F, *]] =
1337+
new LiftValue[F, Resource[F, *]] {
1338+
val applicativeF: Applicative[F] = F
1339+
val applicativeG: Applicative[Resource[F, *]] = catsEffectMonadForResource
1340+
def apply[A](fa: F[A]): Resource[F, A] = Resource.eval(fa)
1341+
}
1342+
1343+
implicit def catsEffectLiftValueForResourceComposed[F[_], G[_]](
1344+
implicit inner: LiftValue[F, G]
1345+
): LiftValue[F, Resource[G, *]] =
1346+
inner.andThen(liftValueImpl(inner.applicativeG))
13111347
}
13121348

13131349
private[effect] trait ResourceHOInstances3 extends ResourceHOInstances4 {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package cats
2+
package effect
3+
package kernel
4+
5+
import cats.data.OptionT
6+
import cats.effect.kernel.testkit.PureConcGenerators._
7+
import cats.effect.kernel.testkit.pure._
8+
import cats.laws.discipline.arbitrary.catsLawsArbitraryForOptionT
9+
import cats.mtl.laws.discipline.{LiftKindTests, LiftValueTests}
10+
import cats.syntax.flatMap._
11+
import cats.syntax.functor._
12+
13+
import org.scalacheck.{Arbitrary, Gen}
14+
15+
import munit.DisciplineSuite
16+
17+
class ResourceSuite extends DisciplineSuite {
18+
type PCT[A] = PureConc[Throwable, A]
19+
20+
private[this] val counter: PCT[Ref[PCT, Long]] = Concurrent[PCT].ref(0)
21+
22+
implicit val eqThrowable: Eq[Throwable] = Eq.fromUniversalEquals
23+
24+
implicit val arbitraryScope: Arbitrary[PCT ~> PCT] =
25+
Arbitrary {
26+
Gen.const {
27+
new (PCT ~> PCT) {
28+
def apply[A](fa: PCT[A]): PCT[A] =
29+
for {
30+
ref <- counter
31+
res <- ref.update(_ + 1) >> fa
32+
} yield res
33+
}
34+
}
35+
}
36+
37+
implicit def arbitraryPCTUnit(): Arbitrary[PCT[Unit]] =
38+
Arbitrary {
39+
Gen.const {
40+
counter.flatMap(_.update(_ * 10)).void
41+
}
42+
}
43+
44+
implicit def eqResource[F[_], A](
45+
implicit F: MonadCancelThrow[F],
46+
eqFAUnit: Eq[F[(A, Unit)]]
47+
): Eq[Resource[F, A]] =
48+
Eq.by {
49+
_.allocated.flatMap {
50+
case (acquire, release) =>
51+
release.map(acquire -> _)
52+
}
53+
}
54+
55+
implicit def arbitraryResource[F[_]: Functor, A](
56+
implicit arbFA: Arbitrary[F[A]],
57+
arbFUnit: Arbitrary[F[Unit]]
58+
): Arbitrary[Resource[F, A]] =
59+
Arbitrary {
60+
for {
61+
acquire <- arbFA.arbitrary
62+
release <- arbFUnit.arbitrary
63+
} yield Resource(acquire.map(_ -> release))
64+
}
65+
66+
checkAll(
67+
"LiftValue[PureConc, Resource[PureConc, *]]",
68+
LiftValueTests[PCT, Resource[PCT, *]].liftValue[Int, Int]
69+
)
70+
checkAll(
71+
"LiftValue[PureConc, Resource[OptionT[PureConc, *], *]]",
72+
LiftValueTests[PCT, Resource[OptionT[PCT, *], *]].liftValue[Int, Int]
73+
)
74+
checkAll(
75+
"LiftKind[PureConc, Resource[PureConc, *]]",
76+
LiftKindTests[PCT, Resource[PCT, *]].liftKind[Int, Int]
77+
)
78+
checkAll(
79+
"LiftKind[PureConc, Resource[OptionT[PureConc, *], *]]",
80+
LiftKindTests[PCT, Resource[OptionT[PCT, *], *]].liftKind[Int, Int]
81+
)
82+
}

0 commit comments

Comments
 (0)