Skip to content

Commit

Permalink
Strict derivation for EmptyK
Browse files Browse the repository at this point in the history
  • Loading branch information
joroKr21 committed Jan 5, 2024
1 parent f88f900 commit ac996e2
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 22 deletions.
39 changes: 27 additions & 12 deletions core/src/main/scala-3/cats/derived/DerivedEmptyK.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package cats.derived

import alleycats.{Empty, EmptyK}
import alleycats.{Empty, EmptyK, Pure}
import shapeless3.deriving.{Const, K1}

import scala.annotation.*
Expand All @@ -23,24 +23,26 @@ object DerivedEmptyK:
import DerivedEmptyK.given
summonInline[DerivedEmptyK[F]].instance

@nowarn("msg=unused import")
inline def strict[F[_]]: EmptyK[F] =
import DerivedEmptyK.given
import Strict.{nested, product}
summonInline[DerivedEmptyK[F]].instance

given [T](using T: Empty[T]): DerivedEmptyK[Const[T]] = new EmptyK[Const[T]]:
def empty[A]: T = T.empty

given nested[F[_], G[_]](using F: => Or[F]): DerivedEmptyK[[x] =>> F[G[x]]] = new EmptyK[[x] =>> F[G[x]]]:
lazy val f = F.unify
def empty[A]: F[G[A]] = f.empty
given nested[F[_], G[_]](using F: => Or[F]): DerivedEmptyK[[x] =>> F[G[x]]] =
Strict.nested(using F.unify)

given nested[F[_], G[_]](using NotGiven[Or[F]])(using
given nested[F[_], G[_]](using ev: NotGiven[Or[F]])(using
F: DerivedPure.Or[F],
G: => Or[G]
): DerivedEmptyK[[x] =>> F[G[x]]] = new EmptyK[[x] =>> F[G[x]]]:
val f = F.unify
lazy val g = G.unify
def empty[A]: F[G[A]] = f.pure(g.empty)
): DerivedEmptyK[[x] =>> F[G[x]]] =
Strict.nested(using ev.asInstanceOf)(using F.unify, G.unify)

given product[F[_]](using inst: K1.ProductInstances[Or, F]): DerivedEmptyK[F] = new EmptyK[F]:
val f = inst.unify
def empty[A]: F[A] = f.construct([f[_]] => (F: EmptyK[f]) => F.empty[A])
given product[F[_]](using inst: K1.ProductInstances[Or, F]): DerivedEmptyK[F] =
Strict.product(using inst.unify)

inline given coproduct[F[_]](using gen: K1.CoproductGeneric[F]): DerivedEmptyK[F] =
gen.withOnly[Or, EmptyK[F]]([f[x] <: F[x]] => (F: Or[f]) => F.unify.asInstanceOf[EmptyK[F]])
Expand All @@ -52,3 +54,16 @@ object DerivedEmptyK:
private[derived] def given_DerivedEmptyK_F[F[_]: DerivedPure.Or, G[_]: Or](
ev: NotGiven[Or[F]]
): DerivedEmptyK[[x] =>> F[G[x]]] = nested(using ev)

object Strict:
given nested[F[_], G[_]](using F: => EmptyK[F]): DerivedEmptyK[[x] =>> F[G[x]]] = new EmptyK[[x] =>> F[G[x]]]:
def empty[A]: F[G[A]] = F.empty

given nested[F[_], G[_]](using NotGiven[EmptyK[F]])(using
F: Pure[F],
G: => EmptyK[G]
): DerivedEmptyK[[x] =>> F[G[x]]] = new EmptyK[[x] =>> F[G[x]]]:
def empty[A]: F[G[A]] = F.pure(G.empty)

given product[F[_]](using inst: K1.ProductInstances[EmptyK, F]): DerivedEmptyK[F] = new EmptyK[F]:
def empty[A]: F[A] = inst.construct([f[_]] => (F: EmptyK[f]) => F.empty[A])
3 changes: 1 addition & 2 deletions core/src/main/scala-3/cats/derived/DerivedMonoid.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ object DerivedMonoid:
Strict.product(using inst.unify)

@deprecated("Kept for binary compatibility", "3.2.0")
private[derived] def given_DerivedMonoid_A[A](using => K0.ProductInstances[Or, A]): DerivedMonoid[A] =
product
private[derived] def given_DerivedMonoid_A[A](using => K0.ProductInstances[Or, A]): DerivedMonoid[A] = product

trait Product[F[x] <: Monoid[x], A](using inst: K0.ProductInstances[F, A])
extends DerivedSemigroup.Product[F, A],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ object DerivedPartialOrder:
import DerivedPartialOrder.given
summonInline[DerivedPartialOrder[A]].instance

@nowarn("msg=unused import")
inline def strict[A]: PartialOrder[A] =
import DerivedPartialOrder.given
import Strict.product
Expand Down
3 changes: 1 addition & 2 deletions core/src/main/scala-3/cats/derived/DerivedSemigroup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ object DerivedSemigroup:
Strict.product(using inst.unify)

@deprecated("Kept for binary compatibility", "3.2.0")
private[derived] def given_DerivedSemigroup_A[A](using => K0.ProductInstances[Or, A]): DerivedSemigroup[A] =
product
private[derived] def given_DerivedSemigroup_A[A](using => K0.ProductInstances[Or, A]): DerivedSemigroup[A] = product

trait Product[F[x] <: Semigroup[x], A](using inst: K0.ProductInstances[F, A]) extends Semigroup[A]:
final override def combine(x: A, y: A): A =
Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala-3/cats/derived/DerivedShowPretty.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ object DerivedShowPretty:
import DerivedShowPretty.given
summonInline[DerivedShowPretty[A]].instance

@nowarn("msg=unused import")
inline def strict[A]: ShowPretty[A] =
import DerivedShowPretty.given
import Strict.product
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/scala-3/cats/derived/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ object strict:
extension (x: CommutativeSemigroup.type)
inline def derived[A]: CommutativeSemigroup[A] = DerivedCommutativeSemigroup.strict[A]
extension (x: CommutativeMonoid.type) inline def derived[A]: CommutativeMonoid[A] = DerivedCommutativeMonoid.strict[A]
extension (x: EmptyK.type) inline def derived[F[_]]: EmptyK[F] = DerivedEmptyK.strict[F]

object semiauto:
inline def eq[A]: Eq[A] = DerivedEq.strict[A]
Expand All @@ -83,6 +84,7 @@ object strict:
inline def monoid[A]: Monoid[A] = DerivedMonoid.strict[A]
inline def commutativeSemigroup[A]: CommutativeSemigroup[A] = DerivedCommutativeSemigroup.strict[A]
inline def commutativeMonoid[A]: CommutativeMonoid[A] = DerivedCommutativeMonoid.strict[A]
inline def emptyK[F[_]]: EmptyK[F] = DerivedEmptyK.strict[F]

object auto:
object eq:
Expand Down
1 change: 1 addition & 0 deletions core/src/test/scala-3/cats/derived/ADTs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ object ADTs:
final case class Second(value: String)
final case class Middle(first: First, second: Option[Second])
final case class Top(middle: Middle)
final case class TopK[A](middle: Middle, k: Option[A])

final case class Address(street: String, city: String, state: String)
final case class ContactInfo(phoneNumber: String, address: Address)
Expand Down
23 changes: 17 additions & 6 deletions core/src/test/scala-3/cats/derived/EmptyKSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,26 @@ class EmptyKSuite extends KittensSuite:
test(s"$instance respects existing instances")(assert(emptyK[BoxColor] == Box(Color(255, 255, 255))))
checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[EmptyK[LOption]]))

locally {
locally:
import auto.emptyK.given
validate("auto.emptyK")
}

locally {
locally:
import semiInstances.given
validate("semiauto.emptyK")
}

locally {
locally:
import strictInstances.given
validate("strict.semiauto.emptyK")
testNoInstance("strict.semiauto.emptyK", "TopK")

locally:
import derivedInstances.*
val instance = "derived.emptyK"
test(s"$instance[CaseClassWOption]")(assert(emptyK[CaseClassWOption].x.value.isEmpty))
test(s"$instance[IList]")(assert(emptyK[IList].x == INil()))
test(s"$instance[Snoc]")(assert(emptyK[Snoc].x == SNil()))
checkAll(s"$instance is Serializable", SerializableTests.serializable(EmptyK[Snoc]))
}

end EmptyKSuite

Expand All @@ -80,6 +82,15 @@ object EmptyKSuite:
given EmptyK[Snoc] = semiauto.emptyK
given EmptyK[BoxColor] = semiauto.emptyK

object strictInstances:
given EmptyK[LOption] = strict.semiauto.emptyK
given EmptyK[PList] = strict.semiauto.emptyK
given EmptyK[CaseClassWOption] = strict.semiauto.emptyK
given EmptyK[NelOption] = strict.semiauto.emptyK
given EmptyK[IList] = strict.semiauto.emptyK
given EmptyK[Snoc] = strict.semiauto.emptyK
given EmptyK[BoxColor] = strict.semiauto.emptyK

object derivedInstances:
case class CaseClassWOption[A](x: ADTs.CaseClassWOption[A]) derives EmptyK
case class IList[A](x: ADTs.IList[A]) derives EmptyK
Expand Down

0 comments on commit ac996e2

Please sign in to comment.