-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
1 parent
55bad35
commit 1096075
Showing
7 changed files
with
163 additions
and
49 deletions.
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
core/src/main/scala-3/cats/derived/DerivedContravariant.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 cats.derived | ||
|
||
import cats.{Contravariant, Functor} | ||
import shapeless3.deriving.{Const, K1} | ||
|
||
import scala.annotation.implicitNotFound | ||
import scala.compiletime.* | ||
|
||
@implicitNotFound("""Could not derive an instance of Contravariant[F] where F = ${F}. | ||
Make sure that F[_] satisfies one of the following conditions: | ||
* it is a constant type [x] =>> T | ||
* it is a nested type [x] =>> G[H[x]] where G: Functor and H: Contravariant | ||
* it is a generic case class where all fields have a Contravariant instance | ||
* it is a generic sealed trait where all subclasses have a Contravariant instance""") | ||
type DerivedContravariant[F[_]] = Derived[Contravariant[F]] | ||
object DerivedContravariant: | ||
type Or[F[_]] = Derived.Or[Contravariant[F]] | ||
inline def apply[F[_]]: Contravariant[F] = | ||
import DerivedContravariant.given | ||
summonInline[DerivedContravariant[F]].instance | ||
|
||
given [T]: DerivedContravariant[Const[T]] = new Contravariant[Const[T]]: | ||
def contramap[A, B](fa: T)(f: B => A): T = fa | ||
|
||
given [F[_], G[_]](using F: DerivedFunctor.Or[F], G: Or[G]): DerivedContravariant[[x] =>> F[G[x]]] = | ||
given Contravariant[G] = G.unify | ||
F.unify.composeContravariant[G] | ||
|
||
given [F[_]](using inst: => K1.Instances[Or, F]): DerivedContravariant[F] = | ||
given K1.Instances[Contravariant, F] = inst.unify | ||
new Generic[Contravariant, F] {} | ||
|
||
trait Generic[T[x[_]] <: Contravariant[x], F[_]](using inst: K1.Instances[T, F]) extends Contravariant[F]: | ||
final override def contramap[A, B](fa: F[A])(f: B => A): F[B] = | ||
inst.map(fa: F[A])([f[_]] => (tf: T[f], fa: f[A]) => tf.contramap(fa)(f)) |
This file was deleted.
Oops, something went wrong.
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
109 changes: 109 additions & 0 deletions
109
core/src/test/scala-3/cats/derived/ContravariantSuite.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,109 @@ | ||
/* | ||
* Copyright (c) 2015 Miles Sabin | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package cats | ||
package derived | ||
|
||
import cats.laws.discipline.* | ||
import cats.laws.discipline.arbitrary.* | ||
import cats.laws.discipline.eq.* | ||
import scala.compiletime.* | ||
|
||
class ContravariantSuite extends KittensSuite: | ||
import ContravariantSuite.* | ||
import TestDefns.* | ||
|
||
inline def contravariantTests[F[_]]: ContravariantTests[F] = ContravariantTests[F](summonInline) | ||
|
||
inline def testContravariant(context: String): Unit = | ||
checkAll(s"$context.Contravariant[OptPred]", contravariantTests[OptPred].contravariant[MiniInt, String, Boolean]) | ||
checkAll(s"$context.Contravariant[TreePred]", contravariantTests[TreePred].contravariant[MiniInt, String, Boolean]) | ||
checkAll(s"$context.Contravariant[ListPred]", contravariantTests[ListPred].contravariant[MiniInt, String, Boolean]) | ||
checkAll( | ||
s"$context.Contravariant[GenericAdtPred]", | ||
contravariantTests[GenericAdtPred].contravariant[MiniInt, String, Boolean] | ||
) | ||
// TODO https://github.com/typelevel/kittens/issues/473 | ||
// checkAll( | ||
// s"$context.Contravariant[InterleavedPred]", | ||
// ContravariantTests[InterleavedPred].contravariant[MiniInt, String, Boolean] | ||
// ) | ||
checkAll( | ||
s"$context.Contravariant[AndCharPred]", | ||
contravariantTests[AndCharPred].contravariant[MiniInt, String, Boolean] | ||
) | ||
checkAll( | ||
s"$context.Contravariant[ListSnocF]", | ||
contravariantTests[ListSnocF].contravariant[MiniInt, String, Boolean] | ||
) | ||
checkAll( | ||
s"$context.Contravariant is Serializable", | ||
SerializableTests.serializable(summonInline[Contravariant[TreePred]]) | ||
) | ||
|
||
// TODO https://github.com/typelevel/kittens/issues/476 | ||
// test(s"$context.Contravariant.contramap is stack safe") { | ||
// val C = summonInline[Contravariant[ListSnocF]] | ||
// val n = 10000 | ||
// val largeBoxed = Snoc.fromSeq((1 until n).map((j: Int) => (i: Int) => i + j)) :: Nil | ||
// val actualBoxed = C.contramap[Int, Int](largeBoxed)((j: Int) => j + 1).flatMap(Snoc.toList) | ||
// val expected = (3 until n + 2).toList | ||
// assert(actualBoxed.map(_.apply(1)) == expected) | ||
// } | ||
|
||
locally { | ||
import auto.contravariant.given | ||
testContravariant("auto") | ||
} | ||
|
||
locally { | ||
import semiInstances.given | ||
testContravariant("semiauto") | ||
} | ||
|
||
object ContravariantSuite: | ||
import TestDefns.* | ||
|
||
type OptPred[A] = Option[A => Boolean] | ||
type ListPred[A] = List[A => Boolean] | ||
type GenericAdtPred[A] = GenericAdt[A => Boolean] | ||
type ListSnocF[A] = List[Snoc[A => Int]] | ||
type InterleavedPred[A] = Interleaved[A => Boolean] | ||
type AndCharPred[A] = (A => Boolean, Char) | ||
type TreePred[A] = Tree[A => Boolean] | ||
|
||
object semiInstances: | ||
implicit val optPred: Contravariant[OptPred] = semiauto.contravariant | ||
implicit val treePred: Contravariant[TreePred] = semiauto.contravariant | ||
implicit val listPred: Contravariant[ListPred] = semiauto.contravariant | ||
implicit val genericAdtPred: Contravariant[GenericAdtPred] = semiauto.contravariant | ||
// implicit val interleavePred: Contravariant[InterleavedPred] = semiauto.contravariant | ||
implicit val andCharPred: Contravariant[AndCharPred] = semiauto.contravariant | ||
implicit val listSnocF: Contravariant[ListSnocF] = semiauto.contravariant | ||
|
||
case class Single[A](value: A => Unit) derives Contravariant | ||
|
||
enum Many[-A] derives Contravariant: | ||
case Naught | ||
case More(value: A => Unit, rest: Many[A]) | ||
|
||
enum AtMostOne[-A] derives Contravariant: | ||
case Naught | ||
case Single(value: A => Unit) | ||
|
||
enum AtLeastOne[-A] derives Contravariant: | ||
case Single(value: A => Unit) | ||
case More(value: A => Unit, rest: Option[AtLeastOne[A]]) |
10 changes: 0 additions & 10 deletions
10
core/src/test/scala-3/cats/derived/ContravariantTests.scala
This file was deleted.
Oops, something went wrong.
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
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