-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for deriveTraverse in scala3
By shamelessly copying code from `kittens`
- Loading branch information
Showing
8 changed files
with
286 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
modules/macros/src/main/scala-3/higherkindness/droste/derivation/Derived.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package higherkindness.droste.derivation | ||
|
||
import shapeless3.deriving.* | ||
import scala.annotation.* | ||
import scala.compiletime.* | ||
|
||
/* | ||
Credit to the `kittens` project. This is a direct copy/paste from there | ||
https://github.com/typelevel/kittens/blob/5b3b7ca168b9636f340b23bc95a4fd1506a26707/core/src/main/scala-3/cats/derived/derived.scala | ||
*/ | ||
|
||
opaque type Derived[A] = A | ||
object Derived: | ||
def apply[A](instance: A): Derived[A] = instance | ||
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]] | ||
|
||
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 [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]) @targetName("unifyK1") def unify: I[F, T] = inst | ||
extension [I[f[_[_[_]]], t[_[_]]] <: K11.Instances[f, t], F[_[_[_]]], T[_[_]]] | ||
(inst: I[Or11[F], T]) @targetName("unifyK11") def unify: I[F, T] = inst | ||
extension [I[f[_[_, _]], t[_, _]] <: K2.Instances[f, t], F[_[_, _]], T[_, _]] | ||
(inst: I[Or2[F], T]) @targetName("unifyK2") def unify: I[F, T] = inst | ||
|
||
sealed abstract class OrInstances: | ||
inline given [A]: Derived.Or[A] = summonFrom { | ||
case instance: A => Derived.Or(instance) | ||
case derived: Derived[A] => Derived.Or(derived.instance) | ||
} |
57 changes: 57 additions & 0 deletions
57
modules/macros/src/main/scala-3/higherkindness/droste/derivation/DerivedFoldable.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package higherkindness.droste.derivation | ||
|
||
import cats.{Eval, Foldable} | ||
import shapeless3.deriving.{Const, Continue, K1} | ||
import scala.compiletime.* | ||
|
||
/* | ||
Credit to the `kittens` project. This is a direct copy/paste from there | ||
https://github.com/typelevel/kittens/blob/5b3b7ca168b9636f340b23bc95a4fd1506a26707/core/src/main/scala-3/cats/derived/foldable.scala | ||
*/ | ||
|
||
type DerivedFoldable[F[_]] = Derived[Foldable[F]] | ||
object DerivedFoldable: | ||
type Or[F[_]] = Derived.Or[Foldable[F]] | ||
inline def apply[F[_]]: Foldable[F] = | ||
import DerivedFoldable.given | ||
summonInline[DerivedFoldable[F]].instance | ||
|
||
given [T]: DerivedFoldable[Const[T]] = new Foldable[Const[T]]: | ||
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 [F[_], G[_]](using F: Or[F], G: Or[G]): DerivedFoldable[[x] =>> F[G[x]]] = | ||
F.unify `compose` G.unify | ||
|
||
given [F[_]](using inst: K1.ProductInstances[Or, F]): DerivedFoldable[F] = | ||
new Product(using inst.unify) {} | ||
|
||
given [F[_]](using inst: => K1.CoproductInstances[Or, F]): DerivedFoldable[F] = | ||
new Coproduct(using inst.unify) {} | ||
|
||
trait Product[T[x[_]] <: Foldable[x], F[_]](using inst: K1.ProductInstances[T, F]) | ||
extends Foldable[F]: | ||
|
||
def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B = | ||
inst.foldLeft[A, B](fa)(b) { [f[_]] => (acc: B, tf: T[f], fa: f[A]) => | ||
Continue(tf.foldLeft(fa, acc)(f)) | ||
} | ||
|
||
def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = | ||
inst.foldRight[A, Eval[B]](fa)(lb) { [f[_]] => (tf: T[f], fa: f[A], acc: Eval[B]) => | ||
Continue(Eval.defer(tf.foldRight(fa, acc)(f))) | ||
} | ||
|
||
trait Coproduct[T[x[_]] <: Foldable[x], F[_]](using inst: K1.CoproductInstances[T, F]) | ||
extends Foldable[F]: | ||
|
||
def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B = | ||
inst.fold[A, B](fa) { [f[_]] => (tf: T[f], fa: f[A]) => | ||
tf.foldLeft(fa, b)(f) | ||
} | ||
|
||
def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = | ||
inst.fold[A, Eval[B]](fa) { [f[_]] => (tf: T[f], fa: f[A]) => | ||
Eval.defer(tf.foldRight(fa, lb)(f)) | ||
} |
35 changes: 35 additions & 0 deletions
35
modules/macros/src/main/scala-3/higherkindness/droste/derivation/DerivedFunctor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package higherkindness.droste.derivation | ||
|
||
import cats.Functor | ||
import shapeless3.deriving.{Const, K1} | ||
import scala.compiletime.* | ||
|
||
/* | ||
Credit to the `kittens` project. This is a direct copy/paste from there | ||
https://github.com/typelevel/kittens/blob/5b3b7ca168b9636f340b23bc95a4fd1506a26707/core/src/main/scala-3/cats/derived/functor.scala | ||
*/ | ||
|
||
type DerivedFunctor[F[_]] = Derived[Functor[F]] | ||
object DerivedFunctor: | ||
type Or[F[_]] = Derived.Or[Functor[F]] | ||
inline def apply[F[_]]: Functor[F] = | ||
import DerivedFunctor.given | ||
summonInline[DerivedFunctor[F]].instance | ||
|
||
given [T]: DerivedFunctor[Const[T]] = new Functor[Const[T]]: | ||
def map[A, B](fa: T)(f: A => B): T = fa | ||
|
||
given [F[_], G[_]](using F: Or[F], G: Or[G]): DerivedFunctor[[x] =>> F[G[x]]] = | ||
F.unify `compose` G.unify | ||
|
||
given [F[_]](using inst: => K1.Instances[Or, F]): DerivedFunctor[F] = | ||
new Generic(using inst.unify) {} | ||
|
||
trait Generic[T[x[_]] <: Functor[x], F[_]](using inst: K1.Instances[T, F]) | ||
extends Functor[F]: | ||
|
||
def map[A, B](fa: F[A])(f: A => B): F[B] = | ||
inst.map(fa: F[A]) { [f[_]] => (tf: T[f], fa: f[A]) => | ||
tf.map(fa)(f) | ||
} |
64 changes: 64 additions & 0 deletions
64
modules/macros/src/main/scala-3/higherkindness/droste/derivation/DerivedTraverse.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package higherkindness.droste.derivation | ||
|
||
import cats.{Applicative, Eval, Traverse} | ||
import shapeless3.deriving.{Const, Continue, K1} | ||
import scala.compiletime.* | ||
|
||
/* | ||
Credit to the `kittens` project. This is a direct copy/paste from there | ||
https://github.com/typelevel/kittens/blob/5b3b7ca168b9636f340b23bc95a4fd1506a26707/core/src/main/scala-3/cats/derived/traverse.scala | ||
*/ | ||
|
||
|
||
type DerivedTraverse[F[_]] = Derived[Traverse[F]] | ||
object DerivedTraverse: | ||
type Or[F[_]] = Derived.Or[Traverse[F]] | ||
inline def apply[F[_]]: Traverse[F] = | ||
import DerivedTraverse.given | ||
summonInline[DerivedTraverse[F]].instance | ||
|
||
given [T]: DerivedTraverse[Const[T]] = new Traverse[Const[T]]: | ||
override def map[A, B](fa: T)(f: A => B): T = fa | ||
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 | ||
def traverse[G[_], A, B](fa: T)(f: A => G[B])(using G: Applicative[G]): G[T] = G.pure(fa) | ||
|
||
given [F[_], G[_]](using F: Or[F], G: Or[G]): DerivedTraverse[[x] =>> F[G[x]]] = | ||
F.unify `compose` G.unify | ||
|
||
given [F[_]](using inst: K1.ProductInstances[Or, F]): DerivedTraverse[F] = | ||
given K1.ProductInstances[Traverse, F] = inst.unify | ||
new Product[Traverse, F] {} | ||
|
||
given [F[_]](using inst: => K1.CoproductInstances[Or, F]): DerivedTraverse[F] = | ||
given K1.CoproductInstances[Traverse, F] = inst.unify | ||
new Coproduct[Traverse, F] {} | ||
|
||
trait Product[T[x[_]] <: Traverse[x], F[_]](using inst: K1.ProductInstances[T, F]) | ||
extends DerivedFunctor.Generic[T, F], DerivedFoldable.Product[T, F], Traverse[F]: | ||
|
||
def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(using G: Applicative[G]): G[F[B]] = | ||
inst.traverse[A, G, B](fa) { [a, b] => (ga: G[a], f: a => b) => | ||
G.map(ga)(f) | ||
} { [a] => (x: a) => | ||
G.pure(x) | ||
} { [a, b] => (gf: G[a => b], ga: G[a]) => | ||
G.ap(gf)(ga) | ||
} { [f[_]] => (tf: T[f], fa: f[A]) => | ||
tf.traverse(fa)(f) | ||
} | ||
|
||
trait Coproduct[T[x[_]] <: Traverse[x], F[_]](using inst: K1.CoproductInstances[T, F]) | ||
extends DerivedFunctor.Generic[T, F], DerivedFoldable.Coproduct[T, F], Traverse[F]: | ||
|
||
def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(using G: Applicative[G]): G[F[B]] = | ||
inst.traverse[A, G, B](fa) { [a, b] => (ga: G[a], f: a => b) => | ||
G.map(ga)(f) | ||
} { [a] => (x: a) => | ||
G.pure(x) | ||
} { [a, b] => (gf: G[a => b], ga: G[a]) => | ||
G.ap(gf)(ga) | ||
} { [f[_]] => (tf: T[f], fa: f[A]) => | ||
tf.traverse(fa)(f) | ||
} |
35 changes: 35 additions & 0 deletions
35
modules/macros/src/main/scala-3/higherkindness/droste/derivation/package.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package higherkindness.droste.derivation | ||
|
||
import cats.* | ||
|
||
/* | ||
Credit to the `kittens` project. This is a direct copy/paste from there | ||
https://github.com/typelevel/kittens/blob/5b3b7ca168b9636f340b23bc95a4fd1506a26707/core/src/main/scala-3/cats/derived/package.scala | ||
*/ | ||
|
||
extension (F: Foldable.type) | ||
inline def derived[F[_]]: Foldable[F] = DerivedFoldable[F] | ||
|
||
extension (F: Functor.type) | ||
inline def derived[F[_]]: Functor[F] = DerivedFunctor[F] | ||
|
||
extension (F: Traverse.type) | ||
inline def derived[F[_]]: Traverse[F] = DerivedTraverse[F] | ||
|
||
object semiauto: | ||
|
||
inline def foldable[F[_]]: Foldable[F] = DerivedFoldable[F] | ||
|
||
inline def functor[F[_]]: Functor[F] = DerivedFunctor[F] | ||
|
||
inline def traverse[F[_]]: Traverse[F] = DerivedTraverse[F] | ||
|
||
|
||
object auto: | ||
|
||
inline given [F[_]]: Foldable[F] = DerivedFoldable[F] | ||
|
||
inline given [F[_]]: Functor[F] = DerivedFunctor[F] | ||
|
||
inline given [F[_]]: Traverse[F] = DerivedTraverse[F] |
45 changes: 45 additions & 0 deletions
45
modules/macros/src/test/scala-3/higherkindness/droste/derivation/DerivedTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package higherkindness.droste.derivation | ||
|
||
import cats.{Foldable, Functor, Traverse} | ||
|
||
class FoldableTests { | ||
|
||
case class Box[A](value: A) derives Foldable | ||
|
||
sealed trait Maybe[+A] derives Foldable | ||
case object Nufin extends Maybe[Nothing] | ||
case class Just[A](value: A) extends Maybe[A] | ||
|
||
sealed trait CList[A] derives Foldable | ||
case object CNil extends CList[Nothing] | ||
case class CCons[A](head: A, tail: CList[A]) extends CList[A] | ||
} | ||
|
||
|
||
class FunctorTests { | ||
|
||
case class Box[A](value: A) derives Functor | ||
|
||
sealed trait Maybe[+A] derives Functor | ||
case object Nufin extends Maybe[Nothing] | ||
case class Just[A](value: A) extends Maybe[A] | ||
|
||
sealed trait CList[A] derives Functor | ||
case object CNil extends CList[Nothing] | ||
case class CCons[A](head: A, tail: CList[A]) extends CList[A] | ||
|
||
} | ||
|
||
|
||
class TraverseTests { | ||
|
||
case class Box[A](value: A) derives Traverse | ||
|
||
sealed trait Maybe[+A] derives Traverse | ||
case object Nufin extends Maybe[Nothing] | ||
case class Just[A](value: A) extends Maybe[A] | ||
|
||
sealed trait CList[A] derives Traverse | ||
case object CNil extends CList[Nothing] | ||
case class CCons[A](head: A, tail: CList[A]) extends CList[A] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters