Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions core/src/main/scala-3/cats/derived/empty.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,34 @@ package cats.derived

import alleycats.Empty
import shapeless3.deriving.K0
import scala.compiletime.summonFrom

object empty extends EmptyDerivation

trait DerivedEmpty[A] extends Empty[A]:
protected def emptyValue(): A
lazy val empty: A = emptyValue()

object DerivedEmpty extends DerivedEmptyLowPriority:
given delegated[A](using A: => Empty[A]): DerivedEmpty[A] =
object DerivedEmpty:
inline given [A]: DerivedEmpty[A] = summonFrom {
case given Empty[A] => delegated
case given K0.Generic[A] => derived
}

def delegated[A](using A: => Empty[A]): DerivedEmpty[A] =
() => A.empty

inline def derived[A](using gen: K0.Generic[A]): DerivedEmpty[A] =
inline gen match
case given K0.ProductGeneric[A] => DerivedEmpty.product
case given K0.CoproductGeneric[A] => DerivedEmpty.coproduct

def product[A](using inst: K0.ProductInstances[DerivedEmpty, A]): DerivedEmpty[A] =
() => inst.construct([A] => (A: DerivedEmpty[A]) => A.empty)

inline def coproduct[A](using gen: K0.CoproductGeneric[A]): DerivedEmpty[A] =
K0.summonFirst[DerivedEmpty, gen.MirroredElemTypes, A]

private[derived] sealed abstract class DerivedEmptyLowPriority:
inline given derived[A](using gen: K0.Generic[A]): DerivedEmpty[A] =
inline gen match
case given K0.ProductGeneric[A] => DerivedEmpty.product
case given K0.CoproductGeneric[A] => DerivedEmpty.coproduct

trait EmptyDerivation:
extension (E: Empty.type)
def derived[A](using instance: DerivedEmpty[A]): Empty[A] = instance