Skip to content

Commit

Permalink
Add type aliases for composed type constructors (#642)
Browse files Browse the repository at this point in the history
Also qualify `Or` type aliases for better readability.
  • Loading branch information
joroKr21 authored Jan 20, 2024
1 parent 6ebfc5f commit 423b7ff
Show file tree
Hide file tree
Showing 31 changed files with 161 additions and 102 deletions.
13 changes: 8 additions & 5 deletions core/src/main/scala-3/cats/derived/Derived.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ object Derived:
extension [A](derived: Derived[A]) def instance: A = derived
given [A]: Conversion[A, Derived[A]] = apply

type Or0[F[_]] = [x] =>> Or[F[x]]
type Or1[F[_[_]]] = [x[_]] =>> Or[F[x]]
type Or11[F[_[_[_]]]] = [x[_[_]]] =>> Or[F[x]]
type Or2[F[_[_, _]]] = [x[_, _]] =>> Or[F[x]]
infix type >>>[F[_], G[_]] = [x] =>> G[F[x]]
infix type <<<[F[_], G[_]] = [x] =>> F[G[x]]

type Or0[F[_]] = [x] =>> Derived.Or[F[x]]
type Or1[F[_[_]]] = [x[_]] =>> Derived.Or[F[x]]
type Or11[F[_[_[_]]]] = [x[_[_]]] =>> Derived.Or[F[x]]
type Or2[F[_[_, _]]] = [x[_, _]] =>> Derived.Or[F[x]]

opaque type Or[A] = A
object Or extends OrInstances:
def apply[A](instance: A): Or[A] = instance
extension [A](or: Or[A]) def unify: A = or
extension [A](derived: Or[A]) def unify: A = derived
extension [I[f[_], t] <: K0.Instances[f, t], F[_], T](inst: I[Or0[F], T])
@targetName("unifyK0") def unify: I[F, T] = inst
extension [I[f[_[_]], t[_]] <: K1.Instances[f, t], F[_[_]], T[_]](inst: I[Or1[F], T])
Expand Down
7 changes: 4 additions & 3 deletions core/src/main/scala-3/cats/derived/DerivedAlternative.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats.derived

import cats.Alternative
import cats.derived.Derived.<<<
import shapeless3.deriving.K1.*

import scala.annotation.*
Expand All @@ -25,10 +26,10 @@ object DerivedAlternative:
summonInline[DerivedAlternative[F]].instance

given nested[F[_], G[_]](using
F: => Or[F],
F: => DerivedAlternative.Or[F],
G: => DerivedApplicative.Or[G]
): DerivedAlternative[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Alternative[[x] =>> F[G[x]]]:
): DerivedAlternative[F <<< G] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Alternative[F <<< G]:
export delegate.*

given product[F[_]](using inst: => ProductInstances[Or, F]): DerivedAlternative[F] =
Expand Down
11 changes: 8 additions & 3 deletions core/src/main/scala-3/cats/derived/DerivedApplicative.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cats.derived

import cats.derived.Derived.<<<
import cats.{Applicative, Monoid}
import shapeless3.deriving.Const
import shapeless3.deriving.K1.*
Expand Down Expand Up @@ -30,15 +31,19 @@ object DerivedApplicative:
def pure[A](x: A): T = T.empty
def ap[A, B](ff: T)(fa: T): T = T.combine(ff, fa)

given nested[F[_], G[_]](using F: => Or[F], G: => Or[G]): DerivedApplicative[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Applicative[[x] =>> F[G[x]]]:
given nested[F[_], G[_]](using
F: => DerivedApplicative.Or[F],
G: => DerivedApplicative.Or[G]
): DerivedApplicative[F <<< G] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Applicative[F <<< G]:
export delegate.*

given [F[_]](using inst: => ProductInstances[Or, F]): DerivedApplicative[F] =
Strict.product(using inst.unify)

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_]: Or, G[_]: Or]: DerivedApplicative[[x] =>> F[G[x]]] = nested
protected given [F[_]: DerivedApplicative.Or, G[_]: DerivedApplicative.Or]: DerivedApplicative[[x] =>> F[G[x]]] =
nested

trait Product[T[f[_]] <: Applicative[f], F[_]](using inst: ProductInstances[T, F])
extends Applicative[F],
Expand Down
9 changes: 5 additions & 4 deletions core/src/main/scala-3/cats/derived/DerivedApply.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cats.derived

import cats.derived.Derived.<<<
import cats.{Apply, Semigroup}
import shapeless3.deriving.Const
import shapeless3.deriving.K1.*
Expand Down Expand Up @@ -30,18 +31,18 @@ object DerivedApply:
def ap[A, B](ff: T)(fa: T): T = T.combine(ff, fa)
def map[A, B](fa: T)(f: A => B): T = fa

given nested[F[_], G[_]](using F: => Or[F], G: => Or[G]): DerivedApply[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Apply[[x] =>> F[G[x]]]:
given nested[F[_], G[_]](using F: => DerivedApply.Or[F], G: => DerivedApply.Or[G]): DerivedApply[F <<< G] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Apply[F <<< G]:
export delegate.*

given [F[_]](using inst: => ProductInstances[Or, F]): DerivedApply[F] =
Strict.product(using inst.unify)

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_]: Or, G[_]: Or]: DerivedApply[[x] =>> F[G[x]]] = nested
protected given [F[_]: DerivedApply.Or, G[_]: DerivedApply.Or]: DerivedApply[[x] =>> F[G[x]]] = nested

trait Product[T[f[_]] <: Apply[f], F[_]](using inst: ProductInstances[T, F]) extends Apply[F]:
private lazy val F = new DerivedFunctor.Generic[T, F] {}
private lazy val F = DerivedFunctor.Strict.product(using inst.widen).instance
final override def map[A, B](fa: F[A])(f: A => B): F[B] = F.map(fa)(f)
final override def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] =
inst.map2(ff, fa)([f[_]] => (F: T[f], ff: f[A => B], fa: f[A]) => F.ap(ff)(fa))
Expand Down
11 changes: 8 additions & 3 deletions core/src/main/scala-3/cats/derived/DerivedContravariant.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats.derived

import cats.Contravariant
import cats.derived.Derived.<<<
import shapeless3.deriving.Const
import shapeless3.deriving.K1.*

Expand Down Expand Up @@ -30,15 +31,19 @@ object DerivedContravariant:
given [T]: DerivedContravariant[Const[T]] = new Contravariant[Const[T]]:
def contramap[A, B](fa: T)(f: B => A): T = fa

given nested[F[_], G[_]](using F: DerivedFunctor.Or[F], G: => Or[G]): DerivedContravariant[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.composeContravariant(using G.unify)) with Contravariant[[x] =>> F[G[x]]]:
given nested[F[_], G[_]](using
F: DerivedFunctor.Or[F],
G: => DerivedContravariant.Or[G]
): DerivedContravariant[F <<< G] =
new Derived.Lazy(() => F.unify.composeContravariant(using G.unify)) with Contravariant[F <<< G]:
export delegate.*

given [F[_]](using inst: => Instances[Or, F]): DerivedContravariant[F] =
generic(using inst.unify)

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_]: DerivedFunctor.Or, G[_]: Or]: DerivedContravariant[[x] =>> F[G[x]]] = nested
protected given [F[_]: DerivedFunctor.Or, G[_]: DerivedContravariant.Or]: DerivedContravariant[[x] =>> F[G[x]]] =
nested

private def generic[F[_]: InstancesOf[Contravariant]]: DerivedContravariant[F] =
new Generic[Contravariant, F] {}
Expand Down
9 changes: 6 additions & 3 deletions core/src/main/scala-3/cats/derived/DerivedEmpty.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ object DerivedEmpty:
import Strict.given
summonInline[DerivedEmpty[A]].instance

given product[A: ProductInstancesOf[Or]]: DerivedEmpty[A] = Strict.product(using ProductInstances.unify)
inline given coproduct[A: CoproductGeneric]: DerivedEmpty[A] = Strict.coproduct
given product[A: ProductInstancesOf[DerivedEmpty.Or]]: DerivedEmpty[A] =
Strict.product(using ProductInstances.unify)

inline given coproduct[A: CoproductGeneric]: DerivedEmpty[A] =
Strict.coproduct

object Strict:
given product[A: ProductInstancesOf[Empty]]: DerivedEmpty[A] =
Empty(ProductInstances.construct([a] => (A: Empty[a]) => A.empty))

inline given coproduct[A: CoproductGeneric]: DerivedEmpty[A] =
Empty(CoproductGeneric.withOnly[Or, A]([a <: A] => (A: Or[a]) => A.unify.empty))
Empty(CoproductGeneric.withOnly[DerivedEmpty.Or, A]([a <: A] => (A: DerivedEmpty.Or[a]) => A.unify.empty))
27 changes: 16 additions & 11 deletions core/src/main/scala-3/cats/derived/DerivedEmptyK.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats.derived

import alleycats.{Empty, EmptyK}
import cats.derived.Derived.<<<
import shapeless3.deriving.Const
import shapeless3.deriving.K1.*

Expand Down Expand Up @@ -32,35 +33,39 @@ object DerivedEmptyK:
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]]]:
given nested[F[_], G[_]](using F: => DerivedEmptyK.Or[F]): DerivedEmptyK[F <<< G] =
new EmptyK[F <<< G]:
lazy val f = F.unify
def empty[A]: F[G[A]] = f.empty

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

given product[F[_]: ProductInstancesOf[Or]]: DerivedEmptyK[F] = Strict.product(using ProductInstances.unify)
inline given coproduct[F[_]: CoproductGeneric]: DerivedEmptyK[F] = Strict.coproduct
given product[F[_]: ProductInstancesOf[DerivedEmptyK.Or]]: DerivedEmptyK[F] =
Strict.product(using ProductInstances.unify)

inline given coproduct[F[_]: CoproductGeneric]: DerivedEmptyK[F] =
Strict.coproduct

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_], G[_]](using F: Or[F]): DerivedEmptyK[[x] =>> F[G[x]]] =
protected given [F[_], G[_]](using F: DerivedEmptyK.Or[F]): DerivedEmptyK[[x] =>> F[G[x]]] =
nested(using F)

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_], G[_]](using
ev: NotGiven[Or[F]]
)(using DerivedPure.Or[F], Or[G]): DerivedEmptyK[[x] =>> F[G[x]]] =
ev: NotGiven[DerivedEmptyK.Or[F]]
)(using DerivedPure.Or[F], DerivedEmptyK.Or[G]): DerivedEmptyK[[x] =>> F[G[x]]] =
nested(using ev)

object Strict:
given product[F[_]: ProductInstancesOf[EmptyK]]: DerivedEmptyK[F] = new EmptyK[F]:
def empty[A]: F[A] = ProductInstances.construct([f[_]] => (F: EmptyK[f]) => F.empty[A])

inline given coproduct[F[_]: CoproductGeneric]: DerivedEmptyK[F] =
CoproductGeneric.withOnly[Or, EmptyK[F]]([f[x] <: F[x]] => (F: Or[f]) => F.unify.asInstanceOf[EmptyK[F]])
CoproductGeneric.withOnly[DerivedEmptyK.Or, EmptyK[F]]:
[f[x] <: F[x]] => (F: DerivedEmptyK.Or[f]) => F.unify.asInstanceOf[EmptyK[F]]
11 changes: 6 additions & 5 deletions core/src/main/scala-3/cats/derived/DerivedFoldable.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package cats.derived

import cats.derived.Derived.<<<
import cats.{Eval, Foldable}
import shapeless3.deriving.{Const, Continue}
import shapeless3.deriving.K1.*
import shapeless3.deriving.{Const, Continue}

import scala.annotation.*
import scala.compiletime.*
Expand Down Expand Up @@ -31,18 +32,18 @@ object DerivedFoldable:
def foldLeft[A, B](fa: T, b: B)(f: (B, A) => B): B = b
def foldRight[A, B](fa: T, lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = lb

given nested[F[_], G[_]](using F: => Or[F], G: => Or[G]): DerivedFoldable[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Foldable[[x] =>> F[G[x]]]:
given nested[F[_], G[_]](using F: => DerivedFoldable.Or[F], G: => DerivedFoldable.Or[G]): DerivedFoldable[F <<< G] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Foldable[F <<< G]:
export delegate.*

given [F[_]: ProductInstancesOf[Or]]: DerivedFoldable[F] =
given [F[_]: ProductInstancesOf[DerivedFoldable.Or]]: DerivedFoldable[F] =
Strict.product(using ProductInstances.unify)

given [F[_]](using => CoproductInstances[Or, F]): DerivedFoldable[F] =
Strict.coproduct

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_]: Or, G[_]: Or]: DerivedFoldable[[x] =>> F[G[x]]] = nested
protected given [F[_]: DerivedFoldable.Or, G[_]: DerivedFoldable.Or]: DerivedFoldable[[x] =>> F[G[x]]] = nested

trait Product[T[f[_]] <: Foldable[f], F[_]](using inst: ProductInstances[T, F]) extends Foldable[F]:
final override def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B =
Expand Down
12 changes: 8 additions & 4 deletions core/src/main/scala-3/cats/derived/DerivedFunctor.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats.derived

import cats.Functor
import cats.derived.Derived.<<<
import shapeless3.deriving.Const
import shapeless3.deriving.K1.*

Expand Down Expand Up @@ -31,21 +32,24 @@ object DerivedFunctor:
given [T]: DerivedFunctor[Const[T]] = new Functor[Const[T]]:
def map[A, B](fa: T)(f: A => B): T = fa

given nested[F[_], G[_]](using F: => Or[F], G: => Or[G]): DerivedFunctor[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Functor[[x] =>> F[G[x]]]:
given nested[F[_], G[_]](using F: => DerivedFunctor.Or[F], G: => DerivedFunctor.Or[G]): DerivedFunctor[F <<< G] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Functor[F <<< G]:
export delegate.*

given nested[F[_], G[_]](using
F: DerivedContravariant.Or[F],
G: DerivedContravariant.Or[G]
): DerivedFunctor[[x] =>> F[G[x]]] =
): DerivedFunctor[F <<< G] =
F.unify.compose(using G.unify)

given [F[_]](using inst: => Instances[Or, F]): DerivedFunctor[F] =
generic(using inst.unify)

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_], G[_]](using F: Or[F], G: Or[G]): DerivedFunctor[[x] =>> F[G[x]]] =
protected given [F[_], G[_]](using
F: DerivedFunctor.Or[F],
G: DerivedFunctor.Or[G]
): DerivedFunctor[[x] =>> F[G[x]]] =
nested(using F, G)

@deprecated("Kept for binary compatibility", "3.2.0")
Expand Down
10 changes: 7 additions & 3 deletions core/src/main/scala-3/cats/derived/DerivedInvariant.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats.derived

import cats.Invariant
import cats.derived.Derived.<<<
import shapeless3.deriving.Const
import shapeless3.deriving.K1.*

Expand Down Expand Up @@ -30,15 +31,18 @@ object DerivedInvariant:
given [T]: DerivedInvariant[Const[T]] = new Invariant[Const[T]]:
def imap[A, B](fa: T)(f: A => B)(g: B => A): T = fa

given nested[F[_], G[_]](using F: => Or[F], G: => Or[G]): DerivedInvariant[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Invariant[[x] =>> F[G[x]]]:
given nested[F[_], G[_]](using
F: => DerivedInvariant.Or[F],
G: => DerivedInvariant.Or[G]
): DerivedInvariant[F <<< G] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with Invariant[F <<< G]:
export delegate.*

given [F[_]](using inst: => Instances[Or, F]): DerivedInvariant[F] =
generic(using inst.unify)

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_]: Or, G[_]: Or]: DerivedInvariant[[x] =>> F[G[x]]] = nested
protected given [F[_]: DerivedInvariant.Or, G[_]: DerivedInvariant.Or]: DerivedInvariant[[x] =>> F[G[x]]] = nested

private def generic[F[_]: InstancesOf[Invariant]]: DerivedInvariant[F] =
new Generic[Invariant, F] {}
Expand Down
17 changes: 9 additions & 8 deletions core/src/main/scala-3/cats/derived/DerivedMonoidK.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cats.derived

import cats.derived.Derived.<<<
import cats.{Monoid, MonoidK}
import shapeless3.deriving.Const
import shapeless3.deriving.K1.*
Expand Down Expand Up @@ -32,14 +33,14 @@ object DerivedMonoidK:
def empty[A]: T = T.empty
def combineK[A](x: T, y: T): T = T.combine(x, y)

given nested[F[_], G[_]](using F: => Or[F]): DerivedMonoidK[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.compose[G]) with MonoidK[[x] =>> F[G[x]]]:
given nested[F[_], G[_]](using F: => DerivedMonoidK.Or[F]): DerivedMonoidK[F <<< G] =
new Derived.Lazy(() => F.unify.compose[G]) with MonoidK[F <<< G]:
export delegate.*

given nested[F[_], G[_]](using
NotGiven[Or[F]]
)(using F: DerivedApplicative.Or[F], G: => Or[G]): DerivedMonoidK[[x] =>> F[G[x]]] =
new MonoidK[[x] =>> F[G[x]]]:
NotGiven[DerivedMonoidK.Or[F]]
)(using F: DerivedApplicative.Or[F], G: => DerivedMonoidK.Or[G]): DerivedMonoidK[F <<< G] =
new MonoidK[F <<< G]:
val f = F.unify
lazy val g = G.unify
def empty[A]: F[G[A]] = f.pure(g.empty[A])
Expand All @@ -49,13 +50,13 @@ object DerivedMonoidK:
Strict.product(using inst.unify)

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_], G[_]](using F: Or[F]): DerivedMonoidK[[x] =>> F[G[x]]] =
protected given [F[_], G[_]](using F: DerivedMonoidK.Or[F]): DerivedMonoidK[[x] =>> F[G[x]]] =
nested(using F)

@deprecated("Kept for binary compatibility", "3.2.0")
protected given [F[_], G[_]](using
ev: NotGiven[Or[F]]
)(using F: DerivedApplicative.Or[F], G: Or[G]): DerivedMonoidK[[x] =>> F[G[x]]] =
ev: NotGiven[DerivedMonoidK.Or[F]]
)(using F: DerivedApplicative.Or[F], G: DerivedMonoidK.Or[G]): DerivedMonoidK[[x] =>> F[G[x]]] =
nested(using ev)

trait Product[T[f[_]] <: MonoidK[f], F[_]](using inst: ProductInstances[T, F])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cats.derived

import cats.NonEmptyAlternative
import cats.derived.Derived.<<<
import shapeless3.deriving.K1.*

import scala.annotation.*
Expand All @@ -25,10 +26,10 @@ object DerivedNonEmptyAlternative:
summonInline[DerivedNonEmptyAlternative[F]].instance

given nested[F[_], G[_]](using
F: => Or[F],
F: => DerivedNonEmptyAlternative.Or[F],
G: => DerivedApplicative.Or[G]
): DerivedNonEmptyAlternative[[x] =>> F[G[x]]] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with NonEmptyAlternative[[x] =>> F[G[x]]]:
): DerivedNonEmptyAlternative[F <<< G] =
new Derived.Lazy(() => F.unify.compose(using G.unify)) with NonEmptyAlternative[F <<< G]:
export delegate.*

given product[F[_]](using inst: => ProductInstances[Or, F]): DerivedNonEmptyAlternative[F] =
Expand Down
Loading

0 comments on commit 423b7ff

Please sign in to comment.