Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sound withFirst and withOnly alternatives to summonFirst and summonOnly #18

Merged
merged 3 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
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
50 changes: 30 additions & 20 deletions modules/deriving/src/main/scala/shapeless3/deriving/kinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ object K0 {
* Summon the first given instance `F[U]` from the tuple `T`.
* Remaining elements of `T` may or may not have an instance of `F`.
*/
inline def summonFirst[F[_], T, U]: F[U] =
Kinds.summonFirst[LiftP[F, T]].asInstanceOf[F[U]]
inline def summonFirst[F[_], T]: F[Any] =
Kinds.summonFirst[LiftP[F, T]].asInstanceOf[F[Any]]

@deprecated("Use summonFirst instead", "3.2.0")
transparent inline def summonFirst0[T]: Any =
Expand All @@ -82,8 +82,8 @@ object K0 {
* Summon the only given instance `F[U]` from the tuple `T`.
* Remaining elements of `T` are guaranteed to not have an instance of `F`.
*/
inline def summonOnly[F[_], T, U]: F[U] =
Kinds.summonOnly[LiftP[F, T]].asInstanceOf[F[U]]
inline def summonOnly[F[_], T]: F[Any] =
Kinds.summonOnly[LiftP[F, T]].asInstanceOf[F[Any]]

/** Ensure that no element of the tuple `T` has an instance of `F`. */
inline def summonNone[F[_], T]: Unit =
Expand All @@ -96,6 +96,8 @@ object K0 {
extension [T](gen: CoproductGeneric[T])
inline def toRepr(o: T): Union[gen.MirroredElemTypes] = o.asInstanceOf
inline def fromRepr(r: Union[gen.MirroredElemTypes]): T = r.asInstanceOf
inline def withFirst[F[_], R](f: [t <: T] => F[t] => R): R = f(summonFirst[F, gen.MirroredElemTypes].asInstanceOf)
inline def withOnly[F[_], R](f: [t <: T] => F[t] => R): R = f(summonOnly[F, gen.MirroredElemTypes].asInstanceOf)

extension [F[_], T](gen: Generic[T])
inline def derive(f: => (ProductGeneric[T] & gen.type) ?=> F[T], g: => (CoproductGeneric[T] & gen.type) ?=> F[T]): F[T] =
Expand Down Expand Up @@ -202,8 +204,8 @@ object K1 {
* Summon the first given instance `F[U]` from the tuple `T`.
* Remaining elements of `T` may or may not have an instance of `F`.
*/
inline def summonFirst[F[_[_]], T[_], U[_]]: F[U] =
Kinds.summonFirst[LiftP[F, T]].asInstanceOf[F[U]]
inline def summonFirst[F[_[_]], T[_]]: F[[_] =>> Any] =
Kinds.summonFirst[LiftP[F, T]].asInstanceOf[F[[_] =>> Any]]

@deprecated("Use summonFirst instead", "3.2.0")
transparent inline def summonFirst0[T]: Any =
Expand All @@ -213,8 +215,8 @@ object K1 {
* Summon the only given instance `F[U]` from the tuple `T`.
* Remaining elements of `T` are guaranteed to not have an instance of `F`.
*/
inline def summonOnly[F[_[_]], T[_], U[_]]: F[U] =
Kinds.summonOnly[LiftP[F, T]].asInstanceOf[F[U]]
inline def summonOnly[F[_[_]], T[_]]: F[[_] =>> Any] =
Kinds.summonOnly[LiftP[F, T]].asInstanceOf[F[[_] =>> Any]]

/** Ensure that no element of the tuple `T` has an instance of `F`. */
inline def summonNone[F[_[_]], T[_]]: Unit =
Expand All @@ -227,6 +229,8 @@ object K1 {
extension [T[_], A](gen: CoproductGeneric[T])
inline def toRepr(o: T[A]): Union[gen.MirroredElemTypes[A]] = o.asInstanceOf
inline def fromRepr(r: Union[gen.MirroredElemTypes[A]]): T[A] = r.asInstanceOf
inline def withFirst[F[_[_]], R](f: [t[x] <: T[x]] => F[t] => R): R = f(summonFirst[F, gen.MirroredElemTypes].asInstanceOf)
inline def withOnly[F[_[_]], R](f: [t[x] <: T[x]] => F[t] => R): R = f(summonOnly[F, gen.MirroredElemTypes].asInstanceOf)

extension [F[_[_]], T[_]](gen: Generic[T]) inline def derive(f: => (ProductGeneric[T] & gen.type) ?=> F[T], g: => (CoproductGeneric[T] & gen.type) ?=> F[T]): F[T] =
inline gen match {
Expand Down Expand Up @@ -329,8 +333,8 @@ object K11 {
* Summon the first given instance `F[U]` from the tuple `T`.
* Remaining elements of `T` may or may not have an instance of `F`.
*/
inline def summonFirst[F[_[_[_]]], T[_[_]], U[_[_]]]: F[U] =
Kinds.summonFirst[LiftP[F, T]].asInstanceOf[F[U]]
inline def summonFirst[F[_[_[_]]], T[_[_]]]: F[[_[_]] =>> Any] =
Kinds.summonFirst[LiftP[F, T]].asInstanceOf[F[[_[_]] =>> Any]]

@deprecated("Use summonFirst instead", "3.2.0")
transparent inline def summonFirst0[T]: Any =
Expand All @@ -340,8 +344,8 @@ object K11 {
* Summon the only given instance `F[U]` from the tuple `T`.
* Remaining elements of `T` are guaranteed to not have an instance of `F`.
*/
inline def summonOnly[F[_[_[_]]], T[_[_]], U[_[_]]]: F[U] =
Kinds.summonOnly[LiftP[F, T]].asInstanceOf[F[U]]
inline def summonOnly[F[_[_[_]]], T[_[_]]]: F[[_[_]] =>> Any] =
Kinds.summonOnly[LiftP[F, T]].asInstanceOf[F[[_[_]] =>> Any]]

/** Ensure that no element of the tuple `T` has an instance of `F`. */
inline def summonNone[F[_[_[_]]], T[_[_]]]: Unit =
Expand All @@ -354,6 +358,8 @@ object K11 {
extension [T[_[_]], A[_]](gen: CoproductGeneric[T])
inline def toRepr(o: T[A]): Union[gen.MirroredElemTypes[A]] = o.asInstanceOf
inline def fromRepr(r: Union[gen.MirroredElemTypes[A]]): T[A] = r.asInstanceOf
inline def withFirst[F[_[_[_]]], R](f: [t[x[_]] <: T[x]] => F[t] => R): R = f(summonFirst[F, gen.MirroredElemTypes].asInstanceOf)
inline def withOnly[F[_[_[_]]], R](f: [t[x[_]] <: T[x]] => F[t] => R): R = f(summonOnly[F, gen.MirroredElemTypes].asInstanceOf)

extension [F[_[_[_]]], T[_[_]]](gen: Generic[T]) inline def derive(f: => (ProductGeneric[T] & gen.type) ?=> F[T], g: => (CoproductGeneric[T] & gen.type) ?=> F[T]): F[T] =
inline gen match {
Expand Down Expand Up @@ -457,8 +463,8 @@ object K2 {
* Summon the first given instance `F[U]` from the tuple `T`.
* Remaining elements of `T` may or may not have an instance of `F`.
*/
inline def summonFirst[F[_[_, _]], T[_, _], U[_, _]]: F[U] =
Kinds.summonFirst[LiftP[F, T]].asInstanceOf[F[U]]
inline def summonFirst[F[_[_, _]], T[_, _]]: F[[_, _] =>> Any] =
Kinds.summonFirst[LiftP[F, T]].asInstanceOf[F[[_, _] =>> Any]]

@deprecated("Use summonFirst instead", "3.2.0")
transparent inline def summonFirst0[T]: Any =
Expand All @@ -468,18 +474,22 @@ object K2 {
* Summon the only given instance `F[U]` from the tuple `T`.
* Remaining elements of `T` are guaranteed to not have an instance of `F`.
*/
inline def summonOnly[F[_[_, _]], T[_, _], U[_, _]]: F[U] =
Kinds.summonOnly[LiftP[F, T]].asInstanceOf[F[U]]
inline def summonOnly[F[_[_, _]], T[_, _]]: F[[_, _] =>> Any] =
Kinds.summonOnly[LiftP[F, T]].asInstanceOf[F[[_, _] =>> Any]]

/** Ensure that no element of the tuple `T` has an instance of `F`. */
inline def summonNone[F[_[_, _]], T[_, _], U[_, _]]: Unit =
Kinds.summonNone[LiftP[F, T]]

extension [T[_, _], A, B](gen: ProductGeneric[T]) inline def toRepr(o: T[A, B]): gen.MirroredElemTypes[A, B] = Tuple.fromProduct(o.asInstanceOf).asInstanceOf[gen.MirroredElemTypes[A, B]]
extension [T[_, _], A, B](gen: ProductGeneric[T]) inline def fromRepr(r: gen.MirroredElemTypes[A, B]): T[A, B] = gen.fromProduct(r.asInstanceOf).asInstanceOf[T[A, B]]
extension [T[_, _], A, B](gen: ProductGeneric[T])
inline def toRepr(o: T[A, B]): gen.MirroredElemTypes[A, B] = Tuple.fromProduct(o.asInstanceOf).asInstanceOf[gen.MirroredElemTypes[A, B]]
inline def fromRepr(r: gen.MirroredElemTypes[A, B]): T[A, B] = gen.fromProduct(r.asInstanceOf).asInstanceOf[T[A, B]]

extension [T[_, _], A, B](gen: CoproductGeneric[T]) inline def toRepr(o: T[A, B]): Union[gen.MirroredElemTypes[A, B]] = o.asInstanceOf
extension [T[_, _], A, B](gen: CoproductGeneric[T]) inline def fromRepr(r: Union[gen.MirroredElemTypes[A, B]]): T[A, B] = r.asInstanceOf
extension [T[_, _], A, B](gen: CoproductGeneric[T])
inline def toRepr(o: T[A, B]): Union[gen.MirroredElemTypes[A, B]] = o.asInstanceOf
inline def fromRepr(r: Union[gen.MirroredElemTypes[A, B]]): T[A, B] = r.asInstanceOf
inline def withFirst[F[_[_, _]], R](f: [t[x, y] <: T[x, y]] => F[t] => R): R = f(summonFirst[F, gen.MirroredElemTypes].asInstanceOf)
inline def withOnly[F[_[_, _]], R](f: [t[x, y] <: T[x, y]] => F[t] => R): R = f(summonOnly[F, gen.MirroredElemTypes].asInstanceOf)

extension [F[_[_, _]], T[_, _]](gen: Generic[T]) inline def derive(f: => (ProductGeneric[T] & gen.type) ?=> F[T], g: => (CoproductGeneric[T] & gen.type) ?=> F[T]): F[T] =
inline gen match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ object Optional:
object NonEmpty:
inline given product[F[_]](using gen: K1.ProductGeneric[F]): NonEmpty[F] =
// Evidence that at least one of the `Optional` instances is `NonEmpty`.
K1.summonFirst[NonEmpty, gen.MirroredElemTypes, Const[Any]]
K1.summonFirst[NonEmpty, gen.MirroredElemTypes]
new Product[F](summonInline)

given coproduct[F[_]](using inst: => K1.CoproductInstances[NonEmpty, F]): NonEmpty[F] with
Expand Down Expand Up @@ -484,10 +484,10 @@ object Empty {
given Empty[Boolean] = mkEmpty(false)

given emptyGen[A](using inst: K0.ProductInstances[Empty, A]): Empty[A] =
mkEmpty(inst.construct([a] => (ma: Empty[a]) => ma.empty))
mkEmpty(inst.construct([a] => (_: Empty[a]).empty))

inline given emptyGenC[A](using gen: K0.CoproductGeneric[A]): Empty[A] =
K0.summonOnly[Empty, gen.MirroredElemTypes, A]
mkEmpty(gen.withOnly[Empty, A]([a <: A] => (_: Empty[a]).empty))

inline def derived[A](using gen: K0.Generic[A]): Empty[A] =
inline gen match
Expand All @@ -512,10 +512,10 @@ object EmptyK {
}

given emptyKGen[A[_]](using inst: K1.ProductInstances[EmptyK, A]): EmptyK[A] =
mkEmptyK([t] => () => inst.construct([f[_]] => (ef: EmptyK[f]) => ef.empty[t]))
mkEmptyK([t] => () => inst.construct([f[_]] => (_: EmptyK[f]).empty[t]))

inline given emptyKGenC[A[_]](using gen: K1.CoproductGeneric[A]): EmptyK[A] =
K1.summonOnly[EmptyK, gen.MirroredElemTypes, A]
mkEmptyK[A]([t] => () => gen.withOnly[EmptyK, A[t]]([a[x] <: A[x]] => (_: EmptyK[a]).empty[t]))

inline def derived[A[_]](using gen: K1.Generic[A]): EmptyK[A] =
inline gen match {
Expand Down Expand Up @@ -563,7 +563,7 @@ object Pure {
mkPure[A]([t] => (a: t) => inst.construct([f[_]] => (af: Alt1.Of[Pure, EmptyK][f]) => af.fold[f[t]](_.pure(a))(_.empty[t])))

inline given pureGenC[A[_]](using gen: K1.CoproductGeneric[A]): Pure[A] =
mkPure[A]([t] => (a: t) => K1.summonFirst[Pure, gen.MirroredElemTypes, A].pure(a))
mkPure[A]([t] => (a: t) => gen.withFirst[Pure, A[t]]([f[x] <: A[x]] => (_: Pure[f]).pure(a)))

inline def derived[A[_]](using gen: K1.Generic[A]): Pure[A] =
inline gen match {
Expand Down