Skip to content

Commit

Permalink
Various improvements
Browse files Browse the repository at this point in the history
- ImplicitNotFound error for SemigroupK/MonoidK
- Replace given priority via traits with NotGiven
  • Loading branch information
TimWSpence committed May 23, 2022
1 parent 009a8d4 commit 0491d43
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 26 deletions.
38 changes: 24 additions & 14 deletions core/src/main/scala-3/cats/derived/DerivedMonoidK.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ package cats.derived
import cats.*
import shapeless3.deriving.{Const, K1}

import scala.annotation.implicitNotFound
import scala.compiletime.*

import scala.util.NotGiven

@implicitNotFound("""Could not derive an instance of MonoidK[F] where F = ${F}.
Make sure that F[_] satisfies one of the following conditions:
* it is a constant type [x] =>> T where T: Monoid
* it is a nested type [x] =>> G[H[x]] where G: MonoidK
* it is a nested type [x] =>> G[H[x]] where G: Applicative and H: MonoidK
* it is a generic case class where all fields have a MonoidK instance
""")
type DerivedMonoidK[F[_]] = Derived[MonoidK[F]]
object DerivedMonoidK extends DerivedMonoidKInstances1:
object DerivedMonoidK:
type Or[F[_]] = Derived.Or[MonoidK[F]]
inline def apply[F[_]]: MonoidK[F] =
import DerivedMonoidK.given
Expand All @@ -20,6 +29,19 @@ object DerivedMonoidK extends DerivedMonoidKInstances1:
given [F[_], G[_]](using F: Or[F]): DerivedMonoidK[[x] =>> F[G[x]]] =
F.unify.compose[G]

given [F[_], G[_]](using
N: NotGiven[Or[F]],
F0: DerivedApplicative.Or[F],
G0: Or[G]
): DerivedMonoidK[[x] =>> F[G[x]]] =
new MonoidK[[x] =>> F[G[x]]]:
val F: Applicative[F] = F0.unify
val G: MonoidK[G] = G0.unify

final override def empty[A]: F[G[A]] = F.pure(G.empty[A])

final override def combineK[A](x: F[G[A]], y: F[G[A]]): F[G[A]] = F.map2(x, y)(G.combineK(_, _))

given [F[_]](using inst: => K1.ProductInstances[Or, F]): DerivedMonoidK[F] =
given K1.ProductInstances[MonoidK, F] = inst.unify
new Product[MonoidK, F] {}
Expand All @@ -28,15 +50,3 @@ object DerivedMonoidK extends DerivedMonoidKInstances1:
extends MonoidK[F],
DerivedSemigroupK.Product[T, F]:
final override def empty[A]: F[A] = inst.construct([t[_]] => (emp: T[t]) => emp.empty[A])

trait DerivedMonoidKInstances1:
import DerivedMonoidK.Or

given [F[_], G[_]](using F0: DerivedApplicative.Or[F], G0: Or[G]): DerivedMonoidK[[x] =>> F[G[x]]] =
new MonoidK[[x] =>> F[G[x]]]:
val F: Applicative[F] = F0.unify
val G: MonoidK[G] = G0.unify

final override def empty[A]: F[G[A]] = F.pure(G.empty[A])

final override def combineK[A](x: F[G[A]], y: F[G[A]]): F[G[A]] = F.map2(x, y)(G.combineK(_, _))
24 changes: 15 additions & 9 deletions core/src/main/scala-3/cats/derived/DerivedSemigroupK.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ package cats.derived
import cats.{Semigroup, SemigroupK}
import shapeless3.deriving.{Const, K1}

import scala.annotation.implicitNotFound
import scala.compiletime.*

import scala.util.NotGiven

@implicitNotFound("""Could not derive an instance of SemigroupK[F] where F = ${F}.
Make sure that F[_] satisfies one of the following conditions:
* it is a constant type [x] =>> T where T: Semigroup
* it is a nested type [x] =>> G[H[x]] where G: SemigroupK
* it is a nested type [x] =>> G[H[x]] where G: Apply and H: SemigroupK
* it is a generic case class where all fields have a SemigroupK instance
""")
type DerivedSemigroupK[F[_]] = Derived[SemigroupK[F]]
object DerivedSemigroupK extends DerivedSemigroupKInstances1:
object DerivedSemigroupK:
type Or[F[_]] = Derived.Or[SemigroupK[F]]
inline def apply[F[_]]: SemigroupK[F] =
import DerivedSemigroupK.given
Expand All @@ -18,17 +27,14 @@ object DerivedSemigroupK extends DerivedSemigroupKInstances1:
given [F[_], G[_]](using F: Or[F]): DerivedSemigroupK[[x] =>> F[G[x]]] =
F.unify.compose[G]

given [F[_], G[_]](using N: NotGiven[Or[F]], F: DerivedApply.Or[F], G: Or[G]): DerivedSemigroupK[[x] =>> F[G[x]]] =
new SemigroupK[[x] =>> F[G[x]]]:
final override def combineK[A](x: F[G[A]], y: F[G[A]]): F[G[A]] = F.unify.map2(x, y)(G.unify.combineK(_, _))

given [F[_]](using inst: => K1.ProductInstances[Or, F]): DerivedSemigroupK[F] =
given K1.ProductInstances[SemigroupK, F] = inst.unify
new Product[SemigroupK, F] {}

trait Product[T[x[_]] <: SemigroupK[x], F[_]](using inst: K1.ProductInstances[T, F]) extends SemigroupK[F]:
final override def combineK[A](x: F[A], y: F[A]): F[A] =
inst.map2[A, A, A](x, y)([t[_]] => (smgrpk: T[t], x: t[A], y: t[A]) => smgrpk.combineK(x, y))

trait DerivedSemigroupKInstances1:
import DerivedSemigroupK.Or

given [F[_], G[_]](using F: DerivedApply.Or[F], G: Or[G]): DerivedSemigroupK[[x] =>> F[G[x]]] =
new SemigroupK[[x] =>> F[G[x]]]:
final override def combineK[A](x: F[G[A]], y: F[G[A]]): F[G[A]] = F.unify.map2(x, y)(G.unify.combineK(_, _))
4 changes: 2 additions & 2 deletions core/src/test/scala-3/cats/derived/MonoidKSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class MonoidKSuite extends KittensSuite {
}

{
import semiInstances.given
import monInstances.given
testMonoidK("semi")
}
}
Expand All @@ -42,7 +42,7 @@ object MonoidKSuite {

type BoxMul[A] = Box[Mul[A]]

object semiInstances {
object monInstances {
implicit val complexProduct: MonoidK[ComplexProduct] = semiauto.monoidK
implicit val caseClassWOption: MonoidK[CaseClassWOption] = semiauto.monoidK
implicit val boxMul: MonoidK[BoxMul] = semiauto.monoidK
Expand Down
1 change: 0 additions & 1 deletion core/src/test/scala-3/cats/derived/SemigroupKSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class SemigroupKSuite extends KittensSuite {

locally {
import auto.semigroupK.given
summon[SemigroupK[[a] =>> Eval[Option[a]]]]
testSemigroupK("auto")
}

Expand Down

0 comments on commit 0491d43

Please sign in to comment.