Skip to content

Commit

Permalink
Scala 3 support (#514)
Browse files Browse the repository at this point in the history
* Setup build for Scala 3

* Hello Scala 3 + Shapeless 3

* For now use test instead of validate

* Use the correct source directory

* Fix version specific source directories (#331)

* Derive Functor, Foldable, Traverse (#330)

* Derive Eq, PartialOrder, Order and Hash (#336)

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Derive Commutative{Semigroup, Monoid} (#341)

* Derive Show with field labels (#340)

* Derive Show with field labels

* Make show safe for empty products

* Use SAM functions to avoid anonymous class generation

* Derive MonoidK hierarchy (#342)

* Scala 3.0, Shapeless 3.0 and other dependencies (#343)

* Cleanup Const - it's provided by shapeless (#345)

Also use the constant type directly for brevity

* Derive Contravariant and Invariant (#346)

* Reducible derivation (#347)

* Deep and Coproduct Empty derivation (#349)

* Use summonFrom to prioritize DerivedEmpty instances (#355)

* Further simplify Empty derivation (#356)

* Generic Derived opaque type for given priority (#359)

* semiauto and auto imports (#353)

* Update sbt and shapeless, use project to derive Show for products (#363)

* Port functor tests (#362)

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Port FoldableSuite to Scala 3 (#374)

* Port ReducibleSuite to Scala 3 (#379)

* Port TraverseSuite to Scala 3 (#377)

* [WIP] Port TraverseSuite to Scala 3

* Update shapeless and fix TraverseSuite

* Port EmptySuite and also solve Empty for Coproducts (#387)

* Port tests for Semigroup and Monoid (#389)

* Rename files according to classes

* Derive Semigroup and Monoid

* Port tests for Semigroup and Monoid

* Port Eq and Hash plus tests (#393)

* Port NonEmptyTraverse derivation to Scala 3 (#394)

* Make derived methods final override (#395)

* Bump Scala and Cats and comment out tests that don't work (#427)

* Bump Scala and comment out tests that don't work

* Update cats

* Bump Scala 2 versions and Kind projector

* Port Show with tests (#433)

* Implement Eq derivation for Dotty

* Restore serializable

* Port Apply to Dotty (#441)

* Port Apply to Dotty

* Apply -> Or

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Make testApply inline

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Port Order to Dotty (#440)

* Port Order to Dotty

* MR comments fixes

* Port Applicative to Dotty (#439)

* Port Applicative to dotty

* Code cleanup

* Comment out Tuple

* Use Apply for deriving Applicative

* Composite Applicative can also be derived

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Merge master to dotty branch (#446)

* Update shapeless to 2.3.6 (#328)

* Update sbt to 1.5.2 (#329)

* Update kind-projector to 0.12.0

* Update sbt-mima-plugin to 0.9.1 (#333)

* Update discipline-munit to 1.0.9 (#335)

* Update alleycats-core, cats-core, ... to 2.6.1 (#334)

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Update kind-projector to 0.13.0 (#337)

* Update shapeless to 2.3.7 (#338)

* Update scala-library, scala-reflect to 2.13.6 (#339)

* Add VSCode .ignore files (#344)

* Update sbt-github-actions to 0.11.0 (#348)

* Update sbt-mima-plugin to 0.9.2 (#350)

* Update scala-library, scala-reflect to 2.12.14 (#351)

* Update sbt to 1.5.3 (#352)

* Update sbt-github-actions to 0.12.0

* Regenerate workflow with sbt-github-actions

* Update sbt-scalajs, scalajs-library, ... to 1.6.0

* Update sbt to 1.5.4 (#365)

* Update sbt-scala-native-crossproject, ... to 1.1.0 (#366)

* Update sbt-scalafmt to 2.4.3 (#367)

* Update sbt to 1.5.5 (#368)

* Update sbt-scalajs, scalajs-compiler, ... to 1.7.0 (#369)

* Update sbt-github-actions to 0.13.0 (#370)

* Update scalafmt-core to 3.0.0 (#371)

* Update scalafmt-core to 3.0.0

* Reformat with scalafmt 3.0.0

* Update sbt-mima-plugin to 1.0.0 (#372)

* Update kind-projector to 0.13.1 (#373)

* Update scalafmt-core to 3.0.1 (#378)

* Update kind-projector to 0.13.2 (#381)

* Update scalafmt-core to 3.0.2 (#380)

* Update scalafmt-core to 3.0.3 (#382)

* Update scalafmt-core to 3.0.4 (#384)

* Update scala-library, scala-reflect to 2.12.15 (#383)

* Update sbt-ci-release to 1.5.9 (#385)

* Update scalafmt-core to 3.0.5 (#386)

* Remove unnecessary instance (#388)

It was merged in cats-core.

* Update scalafmt-core to 3.0.6 (#390)

* Update sbt-mima-plugin to 1.0.1 (#391)

* Update sbt-scalajs, scalajs-compiler, ... to 1.7.1 (#392)

* Update sbt-ci-release to 1.5.10 (#396)

* Update scalafmt-core to 3.0.7 (#397)

* Update auxlib, javalib, nativelib, nscplugin, ... to 0.4.1 (#398)

* Update scalafmt-core to 3.0.8 (#399)

* Update scala-library, scala-reflect to 2.13.7 (#400)

* Update scalafmt-core to 3.1.1 (#403)

* Update scalafmt-core to 3.1.1

* Specify runner dialect explicitly

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Update sbt-scalafmt to 2.4.4 (#404)

* Update scalafmt-core to 3.1.2 (#405)

* Update alleycats-core, cats-core, ... to 2.7.0 (#406)

* Update scalafmt-core to 3.2.0 (#407)

* Update sbt-github-actions to 0.14.2 (#409)

* Update sbt-github-actions to 0.14.2

* Set Java version to Temurin 8

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Update scalafmt-core to 3.2.1 (#410)

* Update sbt-scalafmt to 2.4.5 (#411)

* Update auxlib, javalib, nativelib, nscplugin, ... to 0.4.2 (#412)

* Update sbt to 1.5.6 (#413)

* Update sbt-scalajs, scalajs-compiler, ... to 1.8.0 (#414)

* Update sbt to 1.5.7 (#415)

* Update sbt to 1.5.8 (#416)

* Update scalafmt-core to 3.2.2 (#417)

* Update scalafmt-core to 3.3.0 (#419)

* Update sbt-scalafmt to 2.4.6 (#418)

* Update sbt to 1.6.0 (#420)

* Update sbt to 1.6.1 (#421)

* Update scalafmt-core to 3.3.1 (#424)

* Update scala-library, scala-reflect to 2.13.8 (#426)

* Update scalafmt-core to 3.3.2 (#428)

* Update auxlib, javalib, nativelib, nscplugin, ... to 0.4.3 (#430)

* Update scalafmt-core to 3.3.3 (#431)

* Update scalafmt-core to 3.4.0 (#432)

* Update sbt to 1.6.2 (#434)

* Migrate to sbt-typelevel-ci-release (#429)

* Migrate to sbt-typelevel-ci-release

* Rescope publish settings

* Set tlVersionIntroduced

* Poke ci

* Update to latest sbt-typelevel

* Update scalafmt-core to 3.4.2 (#436)

* Use predefined Apache 2 license (#437)

* Enable snapshots on master (#438)

* Delete .sbtrc

* Publish snapshots from master

* Update sbt-typelevel-ci-release to 0.4.4 (#442)

* Update sbt-typelevel-ci-release to 0.4.4

* Regenerate workflow with sbt-github-actions

* Update sbt-typelevel-ci-release to 0.4.5 (#443)

* Update scalafmt-core to 3.4.3 (#444)

* Update shapeless to 2.3.8 (#445)

* Reformat

* Release from Dotty branch

Co-authored-by: Arman Bilge <armanbilge@gmail.com>

* Update Scala.js to 1.9.0

* Regenerate workflow

* Specify Munit version explicitly

* Don't override scalacOptions

* Check sbt formatting in root project

Co-authored-by: Arman Bilge <armanbilge@gmail.com>

* githubWorkflowGenerate

Co-authored-by: Scala Steward <43047562+scala-steward@users.noreply.github.com>
Co-authored-by: Scala Steward <me@scala-steward.org>
Co-authored-by: Lars Hupel <lars.hupel@mytum.de>
Co-authored-by: Arman Bilge <armanbilge@gmail.com>

* Update to Scala 3.1.2-RC3 and fix outstanding issues (#455)

* Scala 3.1.2 (#464)

* Scala 3.1.2

* Update sbt to 1.7.0-M1 and set scalaOutputVersion

* Port EmptyK to dotty (#448)

* Port EmptyK to dotty

* Fix formatting

* Support EmptyK for sum types

* Refactor EmptyKSuite

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Fix ApplicativeSuite (#465)

* Shapeless 3.1.0 (#468)

Also revert scalaOutputVersion - it's future is unclear

* Derive Pure for Scala 3 (#470)

* Add missing implicit not found messages (#471)

Unfortunately the experiece is subpar, because it doesn't work well
with type aliases which don't support type argument interpolation.

* Port Semigroupk/Monoidk to new scheme (#472)

* Port SemigroupK and MonoidK to new derivation scheme

* WIP port of SemigroupK suite to scala 3

* Nested derivations for SemigroupK

* Priority for derived SemigroupK given instances

* Port scala 2 MonoidK tests to scala 3

* Various improvements

- ImplicitNotFound error for SemigroupK/MonoidK
- Replace given priority via traits with NotGiven

* Use inline in tests

* SemigroupK/MonoidK test for derives syntax

* Port contravariant to new scheme (#475)

* Port SemigroupK and MonoidK to new derivation scheme

* WIP port of SemigroupK suite to scala 3

* Nested derivations for SemigroupK

* Priority for derived SemigroupK given instances

* Port scala 2 MonoidK tests to scala 3

* Various improvements

- ImplicitNotFound error for SemigroupK/MonoidK
- Replace given priority via traits with NotGiven

* Use inline in tests

* SemigroupK/MonoidK test for derives syntax

* Port Contravariant to new derivation scheme

* WIP port scala 2 Contravariant tests to scala 3

* Link commented out tests to issues

* derives syntax tests for Contravariant

* derives syntax tests for Contravariant

* Scala 3 import syntax

* Port invariant to new scheme (#478)

* Port invariant derivation to new scheme

* Port scala 2 invariant tests to scala 3

* Consistent test naming

* WIP extra Invariant instances

* Tests for invariant derivation syntax

* Port partial order to new scheme (#480)

* Port invariant derivation to new scheme

* Port scala 2 invariant tests to scala 3

* Consistent test naming

* WIP extra Invariant instances

* Tests for invariant derivation syntax

* Rename partial order derivation

* Port partial order derivation to new scheme

* Rename to PartialOrderSuite

* Port scala 2 partial order suite to scala 3

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Require Or instances for givens (#486)

* Scala 3 all the tests (#485)

* Replace all usages of implicit with given for Scala 3

Also use braceless syntax in more places.

* Scala 3 all the tests

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Remove obsolete Instances (#487)

* Derive ShowPretty (#490)

* WIP derive ShowPretty

* Derive ShowPretty

* Derive ShowPretty WIP

* Fix show pretty derivations

* Fix ShowPretty tests

Define companion object as scala/scala3#15391
isn't released yet

* Nicer syntax

* Test scala 3 enums (#498)

* Test with scala 3 enums

* More enum tests

* Fix typo

* Add other branches to test enums

* Simplify recursive Gen logic

* Cross-build for Native (#501)

* Cross-build for Native

* Bump munit version

* Bump cats

* Update auto instance implicit error messages

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Upgrade to Scala 3.2 (#513)

* Upgrade to Scala 3.2

Contains a load of fixes that we need, particularly for Mirror synthesis

* Regenerate GH workflow

* Update the rest of dependencies

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Docs (#509)

* Scala 3 docs

* Typo

* Clarify type constructor field limitations

* Extra clarification on the combination of auto and semiauto

* Apply suggestions from code review

Co-authored-by: Georgi Krastev <joro.kr.21@gmail.com>

* Fix and simplify ApplySuite

Co-authored-by: Tim Spence <timothywspence@gmail.com>
Co-authored-by: Ben Plommer <ben.plommer@gmail.com>
Co-authored-by: ​Andrzej Ressel <green.hope9220@fastmail.com>
Co-authored-by: Scala Steward <43047562+scala-steward@users.noreply.github.com>
Co-authored-by: Scala Steward <me@scala-steward.org>
Co-authored-by: Lars Hupel <lars.hupel@mytum.de>
Co-authored-by: Arman Bilge <armanbilge@gmail.com>
  • Loading branch information
8 people committed Sep 12, 2022
1 parent 470ddb3 commit 014ed4a
Show file tree
Hide file tree
Showing 141 changed files with 4,247 additions and 22 deletions.
34 changes: 32 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -28,7 +28,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
scala: [2.12.16, 2.13.8]
scala: [2.12.16, 2.13.8, 3.2.0]
java: [temurin@8]
project: [rootJS, rootJVM, rootNative]
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -114,7 +114,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
scala: [2.13.8]
scala: [3.2.0]
java: [temurin@8]
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -211,6 +211,36 @@ jobs:
tar xf targets.tar
rm targets.tar
- name: Download target directories (3.2.0, rootJS)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootJS

- name: Inflate target directories (3.2.0, rootJS)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (3.2.0, rootJVM)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootJVM

- name: Inflate target directories (3.2.0, rootJVM)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (3.2.0, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootNative

- name: Inflate target directories (3.2.0, rootNative)
run: |
tar xf targets.tar
rm targets.tar
- name: Import signing key
if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE == ''
run: echo $PGP_SECRET | base64 -di | gpg --import
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Expand Up @@ -32,3 +32,10 @@ metals.sbt
.*.swp
.swo
.*.swo

# VS Code
.bloop
.bsp
.metals
.vscode
**/metals.sbt
3 changes: 3 additions & 0 deletions .mergify.yml
Expand Up @@ -18,6 +18,9 @@ pull_request_rules:
- status-success=Build and Test (ubuntu-latest, 2.13.8, temurin@8, rootJS)
- status-success=Build and Test (ubuntu-latest, 2.13.8, temurin@8, rootJVM)
- status-success=Build and Test (ubuntu-latest, 2.13.8, temurin@8, rootNative)
- status-success=Build and Test (ubuntu-latest, 3.2.0, temurin@8, rootJS)
- status-success=Build and Test (ubuntu-latest, 3.2.0, temurin@8, rootJVM)
- status-success=Build and Test (ubuntu-latest, 3.2.0, temurin@8, rootNative)
actions:
merge: {}
- name: Label core PRs
Expand Down
5 changes: 4 additions & 1 deletion .scalafmt.conf
Expand Up @@ -10,4 +10,7 @@ rewrite.redundantBraces.stringInterpolation = true
rewrite.redundantBraces.methodBodies = true
rewrite.redundantBraces.generalExpressions = true
rewriteTokens = { "⇒": "=>", "→": "->", "←": "<-" }
fileOverride { "glob:**/*.sbt" { runner.dialect = scala212 } }
fileOverride {
"glob:**/*.sbt" { runner.dialect = scala212 },
"glob:**/scala-3/**" { runner.dialect = scala3 }
}
107 changes: 106 additions & 1 deletion README.md
Expand Up @@ -24,6 +24,8 @@ libraryDependencies += "org.typelevel" %% "kittens" % "latestVersion" // indicat
[![Scala.js](http://scala-js.org/assets/badges/scalajs-1.5.0.svg)](http://scala-js.org)
[![Latest version](https://img.shields.io/maven-central/v/org.typelevel/kittens_2.12.svg)](https://maven-badges.herokuapp.com/maven-central/org.typelevel/kittens_2.12)

## Scala 2

Instance derivations are available for the following type classes:

* `Eq`, `PartialOrder`, `Order`, `Hash`
Expand Down Expand Up @@ -210,7 +212,109 @@ implicit val showFoo: Show[Foo] = semiauto.show

This way the native instance for `Show[List]` would be used.

### Type class support matrix
## Scala 3

We also offer 3 methods of derivation for Scala 3. All of them have the same behaviour wrt to recursively defining instances:
1. Instances will always be recursively instantiated if necessary
2. Subject to the same type constructor field limitation as the Scala 2 auto and manual semi derivations

### `derives` syntax (recommended)

Kittens for scala 3 supports Scala 3's [derivation syntax](https://docs.scala-lang.org/scala3/reference/contextual/derivation.html).

``` scala
import cats.derived.*

// No instances declared for Name
case class Name(value: String)
case class Person(name: Name, age: Int) derives Eq, Show

enum CList[+A] derives Functor:
case CNil
case CCons(head: A, tail: CList[A])
```

### semiauto derivation

This looks similar to `semiauto` for Scala 2.

``` scala
import cats.derived.semiauto

// No instances declared for Name
case class Name(value: String)
case class Person(name: Name, age: Int)

object Person:
given Eq[Person] = semiauto.eq
given Show[Person] = semiauto.show

enum CList[+A]:
case CNil
case CCons(head: A, tail: CList[A])

object CList:
given Functor[CList] = semiauto.functor
```

As with Scala 2, you can combine `auto` and `semiauto` to avoid the type constructor field limitation:

``` scala
import cats.derived.*

case class Name(value: String)
case class Person(name: Name, age: Int)

case class People(people: List[Person])
object People:
given Show[People] =
import auto.show.given
// Uses the correct List instance despite deriving an instance for Person automatically
semiauto.show
```

`

### auto derivation

This looks similar to `auto` for Scala 2.

``` scala
import cats.derived.auto.eq.given
import cats.derived.auto.show.given
import cats.derived.auto.functor.given

case class Name(value: String)
case class Person(name: Name, age: Int)

enum CList[+A]:
case CNil
case CCons(head: A, tail: CList[A])
```

### Caveats

#### Nested type constructors

We are [currently](https://github.com/typelevel/kittens/issues/473) unable to
derive instances for nested type constructors, such as `Functor[[x] =>>
List[Set[x]]]`.

#### Stack safety

Our derived instances are not stack-safe. This is a departure from the behaviour for Scala 2 because we didn't want to incur the performance penalty of trampolining all instances in `cats.Eval`. If your data-type is recursive or _extremely_ large then you may want to write instances by hand instead.

#### Missing features

Kittens for Scala 3 is built on top of [Shapeless
3](https://github.com/typelevel/shapeless-3) which has a completely different
API than [Shapeless 2](https://github.com/milessabin/shapeless) so we don't
support features like `Sequence` and `Lift`.

`ConsK` derivation is also not supported although we expect this to be
[added](https://github.com/typelevel/kittens/issues/489) in a future release.

## Type class support matrix

Legend:
- `` - all must satisfy a constraint
Expand Down Expand Up @@ -277,4 +381,5 @@ Kittens is built with SBT 1.x, and its master branch is built with Scala 2.13 by
+ Miles Sabin <miles@milessabin.com> [@milessabin](https://twitter.com/milessabin)
+ Qi Wang [Qi77Qi](http://github.com/Qi77Qi)
+ Kailuo Wang <kailuo.wang@gmail.com> [@kailuowang](https://twitter.com/kailuowang)
+ Tim Spence <timothywspence@gmail.com> [timwspence](https://twitter.com/timwspence)
+ Your name here :-)
49 changes: 31 additions & 18 deletions build.sbt
@@ -1,42 +1,54 @@
import sbt._

ThisBuild / crossScalaVersions := Seq("2.12.16", "2.13.8")
ThisBuild / scalaVersion := "2.13.8"
ThisBuild / tlBaseVersion := "2.3"
val scala212 = "2.12.16"
val scala213 = "2.13.8"
val scala3 = "3.2.0"

ThisBuild / crossScalaVersions := Seq(scala212, scala213, scala3)
ThisBuild / scalaVersion := scala3
ThisBuild / tlBaseVersion := "3.0"
ThisBuild / organization := "org.typelevel"

val catsVersion = "2.8.0"
val disciplineMunitVersion = "1.0.9"
val munitVersion = "1.0.0-M6"
val disciplineMunitVersion = "2.0.0-M3"
val kindProjectorVersion = "0.13.2"
val shapelessVersion = "2.3.9"
val shapeless2Version = "2.3.8"
val shapeless3Version = "3.1.0"

lazy val commonSettings = Seq(
scalacOptions := Seq(
scalacOptions ++= Seq(
"-feature",
"-language:higherKinds",
"-language:implicitConversions",
"-unchecked",
"-deprecation",
"-Xfatal-warnings"
),
scalacOptions ++= (
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, v)) if v <= 12 => Seq("-Ypartial-unification")
case _ => Seq.empty
}
),
scalacOptions ++= CrossVersion.partialVersion(scalaVersion.value).toList.flatMap {
case (3, _) => List("-Xmax-inlines", "64")
case (2, 12) => List("-Ypartial-unification")
case _ => Nil
},
resolvers ++= Resolver.sonatypeOssRepos("releases"),
resolvers ++= Resolver.sonatypeOssRepos("snapshots"),
libraryDependencies ++= Seq(
"org.typelevel" %%% "cats-core" % catsVersion,
"org.typelevel" %%% "alleycats-core" % catsVersion,
"com.chuusai" %%% "shapeless" % shapelessVersion,
"org.typelevel" %%% "cats-testkit" % catsVersion % Test,
"org.scalameta" %%% "munit" % "0.7.29" % Test,
"org.typelevel" %%% "discipline-munit" % disciplineMunitVersion % Test,
"org.scala-lang" % "scala-reflect" % scalaVersion.value % Test,
compilerPlugin(("org.typelevel" %% "kind-projector" % kindProjectorVersion).cross(CrossVersion.full))
"org.scalameta" %%% "munit" % munitVersion % Test
),
libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) =>
Seq("org.typelevel" %%% "shapeless3-deriving" % shapeless3Version)
case _ =>
Seq(
"com.chuusai" %%% "shapeless" % shapeless2Version,
"org.scala-lang" % "scala-reflect" % scalaVersion.value % Test,
compilerPlugin(("org.typelevel" %% "kind-projector" % kindProjectorVersion).cross(CrossVersion.full))
)
}),
Test / parallelExecution := false
)

Expand Down Expand Up @@ -74,14 +86,15 @@ ThisBuild / licenses := Seq(License.Apache2)
ThisBuild / developers := List(
Developer("milessabin", "Miles Sabin", "", url("http://milessabin.com/blog")),
Developer("kailuowang", "Kai(luo) Wang", "kailuo.wang@gmail.com", url("http://kailuowang.com/")),
Developer("joroKr21", "Georgi Krastev", "joro.kr.21@gmail.com", url("https://twitter.com/Joro_Kr"))
Developer("joroKr21", "Georgi Krastev", "joro.kr.21@gmail.com", url("https://twitter.com/Joro_Kr")),
Developer("TimWSpence", "Tim Spence", "timothywspence@gmail.com", url("https://twitter.com/timwspence"))
)

ThisBuild / tlCiScalafmtCheck := true
ThisBuild / tlCiReleaseBranches := Seq("master")
ThisBuild / mergifyStewardConfig := Some(
MergifyStewardConfig(
author = "typelevel-steward[bot]",
mergeMinors = true
)
)
ThisBuild / tlCiScalafmtCheck := true
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
36 changes: 36 additions & 0 deletions core/src/main/scala-3/cats/derived/Derived.scala
@@ -0,0 +1,36 @@
package cats.derived

import shapeless3.deriving.*
import scala.annotation.*
import scala.compiletime.*

@implicitNotFound("Could not derive an instance of ${A}")
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)
}
39 changes: 39 additions & 0 deletions core/src/main/scala-3/cats/derived/DerivedApplicative.scala
@@ -0,0 +1,39 @@
package cats.derived

import shapeless3.deriving.{Const, K1}
import cats.{Applicative, Monoid}

import scala.compiletime.*
import shapeless3.deriving.{Continue, K0, Labelling}

import scala.annotation.implicitNotFound
import scala.deriving.Mirror

@implicitNotFound("""Could not derive an instance of Applicative[F] where F = ${F}.
Make sure that F[_] satisfies one of the following conditions:
* it is a constant type [x] =>> T where T: Monoid
* it is a nested type [x] =>> G[H[x]] where G: Applicative and H: Applicative
* it is a generic case class where all fields have an Applicative instance""")
type DerivedApplicative[F[_]] = Derived[Applicative[F]]
object DerivedApplicative:
type Or[F[_]] = Derived.Or[Applicative[F]]

inline def apply[F[_]]: Applicative[F] =
import DerivedApplicative.given
summonInline[DerivedApplicative[F]].instance

given [T](using T: Monoid[T]): DerivedApplicative[Const[T]] = new Applicative[Const[T]]:
def pure[A](x: A): Const[T][A] = T.empty
def ap[A, B](ff: T)(fa: T): Const[T][B] = T.combine(ff, fa)

given [F[_], G[_]](using F: Or[F], G: Or[G]): DerivedApplicative[[x] =>> F[G[x]]] =
F.unify.compose(G.unify)

given [F[_]](using inst: => K1.ProductInstances[Or, F]): DerivedApplicative[F] =
given K1.ProductInstances[Applicative, F] = inst.unify
new Product[Applicative, F] with DerivedApply.Product[Applicative, F] {}

trait Product[T[x[_]] <: Applicative[x], F[_]](using inst: K1.ProductInstances[T, F])
extends Applicative[F],
DerivedApply.Product[T, F]:
override def pure[A](x: A): F[A] = inst.construct([t[_]] => (apl: T[t]) => apl.pure[A](x))

0 comments on commit 014ed4a

Please sign in to comment.