-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]>
- Loading branch information
1 parent
5de791e
commit 21c41a3
Showing
5 changed files
with
131 additions
and
45 deletions.
There are no files selected for viewing
46 changes: 46 additions & 0 deletions
46
core/src/main/scala-3/cats/derived/DerivedPartialOrder.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,46 @@ | ||
package cats.derived | ||
|
||
import cats.{PartialOrder, Show} | ||
import shapeless3.deriving.{Complete, Continue, K0, Labelling} | ||
|
||
import scala.annotation.implicitNotFound | ||
import scala.compiletime.* | ||
import scala.deriving.Mirror | ||
|
||
@implicitNotFound("""Could not derive an instance of PartialOrder[A] where A = ${A}. | ||
Make sure that A satisfies one of the following conditions: | ||
* it is a case class where all fields have a PartialOrder instance | ||
* it is a sealed trait where all subclasses have a PartialOrder instance""") | ||
type DerivedPartialOrder[A] = Derived[PartialOrder[A]] | ||
object DerivedPartialOrder: | ||
type Or[A] = Derived.Or[PartialOrder[A]] | ||
|
||
inline def apply[A]: PartialOrder[A] = | ||
import DerivedPartialOrder.given | ||
summonInline[DerivedPartialOrder[A]].instance | ||
|
||
given product[A](using inst: => K0.ProductInstances[Or, A]): DerivedPartialOrder[A] = | ||
given K0.ProductInstances[PartialOrder, A] = inst.unify | ||
new Product[PartialOrder, A] {} | ||
|
||
given coproduct[A](using inst: => K0.CoproductInstances[Or, A]): DerivedPartialOrder[A] = | ||
given K0.CoproductInstances[PartialOrder, A] = inst.unify | ||
new Coproduct[PartialOrder, A] {} | ||
|
||
trait Product[T[x] <: PartialOrder[x], A](using inst: K0.ProductInstances[T, A]) extends PartialOrder[A]: | ||
|
||
def partialCompare(x: A, y: A): Double = | ||
inst.foldLeft2(x, y)(0: Double)( | ||
[t] => | ||
(acc: Double, ord: T[t], t0: t, t1: t) => { | ||
val cmp = ord.partialCompare(t0, t1) | ||
Complete(cmp != 0)(cmp)(acc) | ||
} | ||
) | ||
|
||
trait Coproduct[T[x] <: PartialOrder[x], A](using inst: K0.CoproductInstances[T, A]) extends PartialOrder[A]: | ||
|
||
def partialCompare(x: A, y: A): Double = | ||
inst.fold2(x, y)(Double.NaN: Double)( | ||
[t] => (ord: T[t], t0: t, t1: t) => ord.partialCompare(t0, t1) | ||
) |
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 was deleted.
Oops, something went wrong.
79 changes: 79 additions & 0 deletions
79
core/src/test/scala-3/cats/derived/PartialOrderSuite.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,79 @@ | ||
/* | ||
* 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.kernel.laws.discipline.{PartialOrderTests, SerializableTests} | ||
import org.scalacheck.{Arbitrary, Cogen} | ||
import scala.compiletime.* | ||
|
||
class PartialOrderSuite extends KittensSuite: | ||
import PartialOrderSuite.* | ||
import TestDefns.* | ||
|
||
inline def partialOrderTests[A]: PartialOrderTests[A] = PartialOrderTests[A](summonInline) | ||
|
||
inline def testPartialOrder(context: String): Unit = | ||
checkAll(s"$context.PartialOrder[IList[Int]]", partialOrderTests[IList[Int]].partialOrder) | ||
checkAll(s"$context.PartialOrder[Inner]", partialOrderTests[Inner].partialOrder) | ||
checkAll(s"$context.PartialOrder[Outer]", partialOrderTests[Outer].partialOrder) | ||
checkAll(s"$context.PartialOrder[Interleaved[Int]]", partialOrderTests[Interleaved[Int]].partialOrder) | ||
checkAll(s"$context.PartialOrder[Tree[Int]]", partialOrderTests[Tree[Int]].partialOrder) | ||
checkAll(s"$context.PartialOrder[Recursive]", partialOrderTests[Recursive].partialOrder) | ||
checkAll(s"$context.PartialOrder[Box[KeyValue]]", partialOrderTests[Box[KeyValue]].partialOrder) | ||
checkAll( | ||
s"$context.PartialOrder is Serialiable", | ||
SerializableTests.serializable(summonInline[PartialOrder[Tree[Int]]]) | ||
) | ||
|
||
test(s"$context.PartialOrder respects existing instances") { | ||
val boxKeyValue = summonInline[PartialOrder[Box[KeyValue]]] | ||
val x = Box(KeyValue("red", 1)) | ||
val y = Box(KeyValue("red", 2)) | ||
val z = Box(KeyValue("blue", 1)) | ||
assert(boxKeyValue.partialCompare(x, y) < 0) | ||
assert(boxKeyValue.partialCompare(y, z).isNaN) | ||
} | ||
|
||
locally { | ||
import auto.partialOrder.given | ||
testPartialOrder("auto") | ||
} | ||
|
||
locally { | ||
import semiInstances.given | ||
testPartialOrder("semiauto") | ||
} | ||
|
||
object PartialOrderSuite: | ||
import TestDefns.* | ||
|
||
object semiInstances: | ||
implicit val iList: PartialOrder[IList[Int]] = semiauto.partialOrder | ||
implicit val inner: PartialOrder[Inner] = semiauto.partialOrder | ||
implicit val outer: PartialOrder[Outer] = semiauto.partialOrder | ||
implicit val interleaved: PartialOrder[Interleaved[Int]] = semiauto.partialOrder | ||
implicit val tree: PartialOrder[Tree[Int]] = semiauto.partialOrder | ||
implicit val recursive: PartialOrder[Recursive] = semiauto.partialOrder | ||
implicit val boxKeyValue: PartialOrder[Box[KeyValue]] = semiauto.partialOrder | ||
|
||
final case class KeyValue(key: String, value: Int) | ||
object KeyValue extends ((String, Int) => KeyValue): | ||
implicit val arbitrary: Arbitrary[KeyValue] = Arbitrary(Arbitrary.arbitrary[(String, Int)].map(tupled)) | ||
implicit val cogen: Cogen[KeyValue] = Cogen[(String, Int)].contramap(kv => kv.key -> kv.value) | ||
|
||
implicit val partialOrder: PartialOrder[KeyValue] = | ||
PartialOrder.from((x, y) => if (x.key == y.key) x.value.toDouble - y.value.toDouble else Double.NaN) |
This file was deleted.
Oops, something went wrong.