diff --git a/core/src/main/scala-2/cats/derived/eq.scala b/core/src/main/scala-2/cats/derived/eq.scala index 460d0efb..e1de6aab 100644 --- a/core/src/main/scala-2/cats/derived/eq.scala +++ b/core/src/main/scala-2/cats/derived/eq.scala @@ -17,8 +17,8 @@ package cats.derived import cats.Eq +import cats.derived.util.VersionSpecific.{Lazy, OrElse} import shapeless._ -import util.VersionSpecific.{OrElse, Lazy} import scala.annotation.implicitNotFound @@ -32,7 +32,7 @@ object MkEq extends MkEqDerivation { def apply[A](implicit ev: MkEq[A]): MkEq[A] = ev } -abstract private[derived] class MkEqDerivation { +abstract private[derived] class MkEqDerivation extends MkEqSingletons { implicit val mkEqHNil: MkEq[HNil] = (_, _) => true implicit val mkEqCNil: MkEq[CNil] = (_, _) => true @@ -49,3 +49,8 @@ abstract private[derived] class MkEqDerivation { implicit def mkEqGeneric[A, R](implicit A: Generic.Aux[A, R], R: Lazy[MkEq[R]]): MkEq[A] = (x, y) => R.value.eqv(A.to(x), A.to(y)) } + +abstract private[derived] class MkEqSingletons { + implicit def mkEqSingleton[A: Witness.Aux]: MkEq[A] = + (_, _) => true +} diff --git a/core/src/main/scala-2/cats/derived/hash.scala b/core/src/main/scala-2/cats/derived/hash.scala index 7750ef24..ff1777a7 100644 --- a/core/src/main/scala-2/cats/derived/hash.scala +++ b/core/src/main/scala-2/cats/derived/hash.scala @@ -28,8 +28,8 @@ private[derived] trait HashBuilder[A] extends Serializable { } } +import cats.derived.util.VersionSpecific.{Lazy, OrElse} import shapeless._ -import util.VersionSpecific.{OrElse, Lazy} private[derived] object HashBuilder { @@ -52,6 +52,17 @@ private[derived] object HashBuilder { } abstract private[derived] class MkHashDerivation extends MkHashGenericProduct { + // These instances support singleton types unlike the instances in Cats' kernel. + implicit def mkHashBoolean[A <: Boolean]: MkHash[A] = universal + implicit def mkHashByte[A <: Byte]: MkHash[A] = universal + implicit def mkHashShort[A <: Short]: MkHash[A] = universal + implicit def mkHashInt[A <: Int]: MkHash[A] = universal + implicit def mkHashLong[A <: Long]: MkHash[A] = universal + implicit def mkHashFloat[A <: Float]: MkHash[A] = universal + implicit def mkHashDouble[A <: Double]: MkHash[A] = universal + implicit def mkHashChar[A <: Char]: MkHash[A] = universal + implicit def mkHashString[A <: String]: MkHash[A] = universal + implicit def mkHashSymbol[A <: Symbol]: MkHash[A] = universal implicit val mkHashCNil: MkHash[CNil] = instance(_ => 0, (_, _) => true) @@ -99,6 +110,7 @@ abstract private[derived] class MkHashGenericHList extends MkHashGenericCoproduc } abstract private[derived] class MkHashGenericCoproduct { + private[this] val universalInstance = instance[Any](_.hashCode, _ == _) implicit def mkHashGenericCoproduct[A, R <: Coproduct](implicit A: Generic.Aux[A, R], @@ -108,6 +120,9 @@ abstract private[derived] class MkHashGenericCoproduct { (x, y) => R.value.eqv(A.to(x), A.to(y)) ) + protected def universal[A]: MkHash[A] = + universalInstance.asInstanceOf[MkHash[A]] + protected def instance[A](f: A => Int, g: (A, A) => Boolean): MkHash[A] = new MkHash[A] { def hash(x: A) = f(x) diff --git a/core/src/main/scala-2/cats/derived/order.scala b/core/src/main/scala-2/cats/derived/order.scala index 1c84296a..bd2138e0 100644 --- a/core/src/main/scala-2/cats/derived/order.scala +++ b/core/src/main/scala-2/cats/derived/order.scala @@ -7,7 +7,7 @@ * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless rorduired by applicable law or agreed to in writing, software + * 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 @@ -17,8 +17,8 @@ package cats.derived import cats.Order +import cats.derived.util.VersionSpecific.{Lazy, OrElse} import shapeless._ -import util.VersionSpecific.{OrElse, Lazy} import scala.annotation.implicitNotFound @@ -32,7 +32,7 @@ object MkOrder extends MkOrderDerivation { def apply[A](implicit ev: MkOrder[A]): MkOrder[A] = ev } -abstract private[derived] class MkOrderDerivation { +abstract private[derived] class MkOrderDerivation extends MkOrderSingletons { implicit val mkOrderHNil: MkOrder[HNil] = (_, _) => 0 implicit val mkOrderCNil: MkOrder[CNil] = (_, _) => 0 @@ -52,3 +52,8 @@ abstract private[derived] class MkOrderDerivation { implicit def mkOrderGeneric[A, R](implicit A: Generic.Aux[A, R], R: Lazy[MkOrder[R]]): MkOrder[A] = (x, y) => R.value.compare(A.to(x), A.to(y)) } + +abstract private[derived] class MkOrderSingletons { + implicit def mkOrderSingleton[A: Witness.Aux]: MkOrder[A] = + (_, _) => 0 +} diff --git a/core/src/main/scala-2/cats/derived/partialOrder.scala b/core/src/main/scala-2/cats/derived/partialOrder.scala index 30ccac75..ad2fe194 100644 --- a/core/src/main/scala-2/cats/derived/partialOrder.scala +++ b/core/src/main/scala-2/cats/derived/partialOrder.scala @@ -7,7 +7,7 @@ * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless rorduired by applicable law or agreed to in writing, software + * 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 @@ -17,8 +17,8 @@ package cats.derived import cats.PartialOrder +import cats.derived.util.VersionSpecific.{Lazy, OrElse} import shapeless._ -import util.VersionSpecific.{OrElse, Lazy} import scala.annotation.implicitNotFound @@ -32,7 +32,7 @@ object MkPartialOrder extends MkPartialOrderDerivation { def apply[A](implicit ev: MkPartialOrder[A]): MkPartialOrder[A] = ev } -abstract private[derived] class MkPartialOrderDerivation { +abstract private[derived] class MkPartialOrderDerivation extends MkPartialOrderSingletons { implicit val mkPartialOrderHNil: MkPartialOrder[HNil] = (_, _) => 0 implicit val mkPartialOrderCNil: MkPartialOrder[CNil] = (_, _) => 0 @@ -58,3 +58,8 @@ abstract private[derived] class MkPartialOrderDerivation { R: Lazy[MkPartialOrder[R]] ): MkPartialOrder[A] = (x, y) => R.value.partialCompare(A.to(x), A.to(y)) } + +abstract private[derived] class MkPartialOrderSingletons { + implicit def mkPartialOrderSingleton[A: Witness.Aux]: MkPartialOrder[A] = + (_, _) => 0 +} diff --git a/core/src/main/scala-2/cats/derived/pure.scala b/core/src/main/scala-2/cats/derived/pure.scala index f633d359..cd01ec09 100644 --- a/core/src/main/scala-2/cats/derived/pure.scala +++ b/core/src/main/scala-2/cats/derived/pure.scala @@ -17,8 +17,8 @@ package cats.derived import alleycats.{Empty, Pure} +import cats.derived.util.VersionSpecific.OrElse import shapeless._ -import util.VersionSpecific.OrElse import scala.annotation.implicitNotFound @@ -50,6 +50,11 @@ abstract private[derived] class MkPureDerivation extends MkPureNested { abstract private[derived] class MkPureNested extends MkPureCons { + implicit def mkPureSingleton[T](implicit T: Witness.Aux[T]): MkPure[Const[T]#λ] = + new MkPure[Const[T]#λ] { + def pure[A](a: A) = T.value + } + implicit def mkPureNested[F[_]](implicit F: Split1[F, PureOrMk, PureOrMk]): MkPure[F] = new MkPure[F] { def pure[A](a: A) = F.pack(F.fo.unify.pure(F.fi.unify.pure(a))) diff --git a/core/src/main/scala-2/cats/derived/show.scala b/core/src/main/scala-2/cats/derived/show.scala index c38ed687..3013ebfa 100644 --- a/core/src/main/scala-2/cats/derived/show.scala +++ b/core/src/main/scala-2/cats/derived/show.scala @@ -1,9 +1,10 @@ package cats package derived +import cats.Show.ContravariantShow +import cats.derived.util.VersionSpecific.{Lazy, OrElse} import shapeless._ import shapeless.labelled._ -import util.VersionSpecific.{Lazy, OrElse} import scala.annotation.implicitNotFound import scala.reflect.ClassTag @@ -31,7 +32,7 @@ sealed abstract private[derived] class MkShowDerivation extends MkShowGenericCop implicit def mkShowLabelledHCons[K <: Symbol, V, T <: HList](implicit K: Witness.Aux[K], - V: Show[V] OrElse MkShow[V], + V: ContravariantShow[V] OrElse MkShow[V], T: MkShow[T] ): MkShow[FieldType[K, V] :: T] = { case v :: t => val name = K.value.name diff --git a/core/src/main/scala-2/cats/derived/showPretty.scala b/core/src/main/scala-2/cats/derived/showPretty.scala index 202ee3bb..19e4561d 100644 --- a/core/src/main/scala-2/cats/derived/showPretty.scala +++ b/core/src/main/scala-2/cats/derived/showPretty.scala @@ -1,6 +1,7 @@ package cats.derived import cats.Show +import cats.Show.ContravariantShow import cats.derived.util.VersionSpecific.{Lazy, OrElse} import shapeless._ import shapeless.labelled._ @@ -33,7 +34,7 @@ sealed abstract private[derived] class MkShowPrettyDerivation extends MkShowPret implicit def mkShowPrettyLabelledHCons[K <: Symbol, V, T <: HList](implicit K: Witness.Aux[K], - V: Show[V] OrElse MkShowPretty[V], + V: ContravariantShow[V] OrElse MkShowPretty[V], T: MkShowPretty[T] ): MkShowPretty[FieldType[K, V] :: T] = { case v :: t => val name = K.value.name @@ -71,7 +72,7 @@ sealed abstract private[derived] class MkShowPrettyDerivation extends MkShowPret sealed abstract private[derived] class MkShowPrettyGenericCoproduct { - protected def mkShowLines[A](show: Show[A] OrElse MkShowPretty[A])(a: A): List[String] = + protected def mkShowLines[A](show: ContravariantShow[A] OrElse MkShowPretty[A])(a: A): List[String] = show.fold( { case pretty: ShowPretty[A] => pretty.showLines(a) diff --git a/core/src/main/scala-3/cats/derived/DerivedEq.scala b/core/src/main/scala-3/cats/derived/DerivedEq.scala index 85ebab9c..583e29ca 100644 --- a/core/src/main/scala-3/cats/derived/DerivedEq.scala +++ b/core/src/main/scala-3/cats/derived/DerivedEq.scala @@ -17,6 +17,9 @@ object DerivedEq: import DerivedEq.given summonInline[DerivedEq[A]].instance + given singleton[A <: Singleton: ValueOf]: DerivedEq[A] = + Eq.allEqual + given product[A](using inst: => K0.ProductInstances[Or, A]): DerivedEq[A] = given K0.ProductInstances[Eq, A] = inst.unify new Product[Eq, A] {} @@ -26,11 +29,9 @@ object DerivedEq: new Coproduct[Eq, A] {} trait Product[F[x] <: Eq[x], A](using inst: K0.ProductInstances[F, A]) extends Eq[A]: - final override def eqv(x: A, y: A): Boolean = inst.foldLeft2(x, y)(true: Boolean)( + final override def eqv(x: A, y: A): Boolean = inst.foldLeft2(x, y)(true: Boolean): [t] => (acc: Boolean, eqt: F[t], x: t, y: t) => Complete(!eqt.eqv(x, y))(false)(true) - ) trait Coproduct[F[x] <: Eq[x], A](using inst: K0.CoproductInstances[F, A]) extends Eq[A]: - final override def eqv(x: A, y: A): Boolean = inst.fold2(x, y)(false)( + final override def eqv(x: A, y: A): Boolean = inst.fold2(x, y)(false): [t] => (eqt: F[t], x: t, y: t) => eqt.eqv(x, y) - ) diff --git a/core/src/main/scala-3/cats/derived/DerivedHash.scala b/core/src/main/scala-3/cats/derived/DerivedHash.scala index 356417d9..a1e9101a 100644 --- a/core/src/main/scala-3/cats/derived/DerivedHash.scala +++ b/core/src/main/scala-3/cats/derived/DerivedHash.scala @@ -18,6 +18,18 @@ object DerivedHash: import DerivedHash.given summonInline[DerivedHash[A]].instance + // These instances support singleton types unlike the instances in Cats' kernel. + given boolean[A <: Boolean]: DerivedHash[A] = Hash.fromUniversalHashCode + given byte[A <: Byte]: DerivedHash[A] = Hash.fromUniversalHashCode + given short[A <: Short]: DerivedHash[A] = Hash.fromUniversalHashCode + given int[A <: Int]: DerivedHash[A] = Hash.fromUniversalHashCode + given long[A <: Long]: DerivedHash[A] = Hash.fromUniversalHashCode + given float[A <: Float]: DerivedHash[A] = Hash.fromUniversalHashCode + given double[A <: Double]: DerivedHash[A] = Hash.fromUniversalHashCode + given char[A <: Char]: DerivedHash[A] = Hash.fromUniversalHashCode + given string[A <: String]: DerivedHash[A] = Hash.fromUniversalHashCode + given symbol[A <: Symbol]: DerivedHash[A] = Hash.fromUniversalHashCode + given product[A <: scala.Product](using inst: => K0.ProductInstances[Or, A]): DerivedHash[A] = given K0.ProductInstances[Hash, A] = inst.unify new Product[Hash, A] {} @@ -35,12 +47,9 @@ object DerivedHash: val prefix = x.productPrefix.hashCode if arity <= 0 then prefix else - MurmurHash3.finalizeHash( - inst.foldLeft[Int](x)(MurmurHash3.mix(MurmurHash3.productSeed, prefix))( - [t] => (acc: Int, h: F[t], x: t) => Continue(MurmurHash3.mix(acc, h.hash(x))) - ), - arity - ) + val hash = inst.foldLeft[Int](x)(MurmurHash3.mix(MurmurHash3.productSeed, prefix)): + [t] => (acc: Int, h: F[t], x: t) => Continue(MurmurHash3.mix(acc, h.hash(x))) + MurmurHash3.finalizeHash(hash, arity) trait Coproduct[F[x] <: Hash[x], A](using inst: K0.CoproductInstances[F, A]) extends DerivedEq.Coproduct[F, A], diff --git a/core/src/main/scala-3/cats/derived/DerivedOrder.scala b/core/src/main/scala-3/cats/derived/DerivedOrder.scala index 25e2a5b9..eed67c76 100644 --- a/core/src/main/scala-3/cats/derived/DerivedOrder.scala +++ b/core/src/main/scala-3/cats/derived/DerivedOrder.scala @@ -1,11 +1,10 @@ package cats.derived -import cats.{Order, Show} -import shapeless3.deriving.{Complete, Continue, K0, Labelling} +import cats.Order +import shapeless3.deriving.{Complete, K0} import scala.annotation.implicitNotFound import scala.compiletime.* -import scala.deriving.Mirror @implicitNotFound("""Could not derive an instance of Order[A] where A = ${A}. Make sure that A satisfies one of the following conditions: @@ -19,6 +18,9 @@ object DerivedOrder: import DerivedOrder.given summonInline[DerivedOrder[A]].instance + given singleton[A <: Singleton: ValueOf]: DerivedOrder[A] = + Order.allEqual + given product[A](using inst: => K0.ProductInstances[Or, A]): DerivedOrder[A] = given K0.ProductInstances[Order, A] = inst.unify new Product[Order, A] {} @@ -28,18 +30,14 @@ object DerivedOrder: new Coproduct[Order, A] {} trait Product[T[x] <: Order[x], A](using inst: K0.ProductInstances[T, A]) extends Order[A]: - def compare(x: A, y: A): Int = - inst.foldLeft2(x, y)(0: Int)( + inst.foldLeft2(x, y)(0: Int): [t] => (acc: Int, ord: T[t], t0: t, t1: t) => val cmp = ord.compare(t0, t1) Complete(cmp != 0)(cmp)(acc) - ) trait Coproduct[T[x] <: Order[x], A](using inst: K0.CoproductInstances[T, A]) extends Order[A]: - def compare(x: A, y: A): Int = - inst.fold2(x, y)((x: Int, y: Int) => x - y)( + inst.fold2(x, y)((x: Int, y: Int) => x - y): [t] => (ord: T[t], t0: t, t1: t) => ord.compare(t0, t1) - ) diff --git a/core/src/main/scala-3/cats/derived/DerivedPartialOrder.scala b/core/src/main/scala-3/cats/derived/DerivedPartialOrder.scala index 46a7bab1..c4b96440 100644 --- a/core/src/main/scala-3/cats/derived/DerivedPartialOrder.scala +++ b/core/src/main/scala-3/cats/derived/DerivedPartialOrder.scala @@ -1,11 +1,10 @@ package cats.derived -import cats.{PartialOrder, Show} -import shapeless3.deriving.{Complete, Continue, K0, Labelling} +import cats.{Order, PartialOrder} +import shapeless3.deriving.{Complete, K0} 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: @@ -19,6 +18,9 @@ object DerivedPartialOrder: import DerivedPartialOrder.given summonInline[DerivedPartialOrder[A]].instance + given singleton[A <: Singleton: ValueOf]: DerivedPartialOrder[A] = + Order.allEqual + given product[A](using inst: => K0.ProductInstances[Or, A]): DerivedPartialOrder[A] = given K0.ProductInstances[PartialOrder, A] = inst.unify new Product[PartialOrder, A] {} @@ -28,18 +30,14 @@ object DerivedPartialOrder: 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)( + 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)( + inst.fold2(x, y)(Double.NaN: Double): [t] => (ord: T[t], t0: t, t1: t) => ord.partialCompare(t0, t1) - ) diff --git a/core/src/main/scala-3/cats/derived/DerivedPure.scala b/core/src/main/scala-3/cats/derived/DerivedPure.scala index 5a68a22f..666dd32f 100644 --- a/core/src/main/scala-3/cats/derived/DerivedPure.scala +++ b/core/src/main/scala-3/cats/derived/DerivedPure.scala @@ -23,6 +23,10 @@ object DerivedPure: new Pure[Const[T]]: def pure[A](a: A) = T.empty + given [T <: Singleton: ValueOf]: DerivedPure[Const[T]] = + new Pure[Const[T]]: + def pure[A](a: A) = valueOf[T] + given [F[_], G[_]](using F: Or[F], G: Or[G]): DerivedPure[[x] =>> F[G[x]]] = new Pure[[x] =>> F[G[x]]]: def pure[A](a: A) = F.unify.pure(G.unify.pure(a)) diff --git a/core/src/main/scala-3/cats/derived/DerivedShow.scala b/core/src/main/scala-3/cats/derived/DerivedShow.scala index 9e7bea9e..c6204808 100644 --- a/core/src/main/scala-3/cats/derived/DerivedShow.scala +++ b/core/src/main/scala-3/cats/derived/DerivedShow.scala @@ -1,11 +1,10 @@ package cats.derived import cats.Show -import shapeless3.deriving.{Continue, K0, Labelling} +import shapeless3.deriving.{K0, Labelling} import scala.annotation.implicitNotFound import scala.compiletime.* -import scala.deriving.Mirror @implicitNotFound("""Could not derive an instance of Show[A] where A = ${A}. Make sure that A satisfies one of the following conditions: @@ -19,6 +18,18 @@ object DerivedShow: import DerivedShow.given summonInline[DerivedShow[A]].instance + // These instances support singleton types unlike the instances in Cats' core. + given boolean[A <: Boolean]: DerivedShow[A] = Show.fromToString + given byte[A <: Byte]: DerivedShow[A] = Show.fromToString + given short[A <: Short]: DerivedShow[A] = Show.fromToString + given int[A <: Int]: DerivedShow[A] = Show.fromToString + given long[A <: Long]: DerivedShow[A] = Show.fromToString + given float[A <: Float]: DerivedShow[A] = Show.fromToString + given double[A <: Double]: DerivedShow[A] = Show.fromToString + given char[A <: Char]: DerivedShow[A] = Show.fromToString + given string[A <: String]: DerivedShow[A] = Show.fromToString + given symbol[A <: Symbol]: DerivedShow[A] = Show.fromToString + given [A](using inst: K0.ProductInstances[Or, A], labelling: Labelling[A]): DerivedShow[A] = given K0.ProductInstances[Show, A] = inst.unify new Product[Show, A] {} diff --git a/core/src/main/scala-3/cats/derived/DerivedShowPretty.scala b/core/src/main/scala-3/cats/derived/DerivedShowPretty.scala index 195e9b2b..eb4ef071 100644 --- a/core/src/main/scala-3/cats/derived/DerivedShowPretty.scala +++ b/core/src/main/scala-3/cats/derived/DerivedShowPretty.scala @@ -1,11 +1,10 @@ package cats.derived import cats.Show -import shapeless3.deriving.{Continue, K0, Labelling} +import shapeless3.deriving.{K0, Labelling} import scala.annotation.implicitNotFound import scala.compiletime.* -import scala.deriving.Mirror trait ShowPretty[A] extends Show[A]: def showLines(a: A): List[String] @@ -23,15 +22,32 @@ object DerivedShowPretty: opaque type Or[A] = A => List[String] object Or: extension [A](or: Or[A]) def apply(a: A): List[String] = or(a) - inline given [A]: Or[A] = summonFrom { - case instance: Show[A] => instance.show(_).split(System.lineSeparator).toList - case derived: DerivedShowPretty[A] => derived.instance.showLines(_) - } + inline given [A]: Or[A] = summonFrom: + case instance: Show[A] => fromShow(instance) + case derived: DerivedShowPretty[A] => fromShow(derived.instance) + private def fromShow[A](instance: Show[A]): Or[A] = instance match + case pretty: ShowPretty[A] => pretty.showLines + case _ => instance.show(_).split(System.lineSeparator).toList inline def apply[A]: ShowPretty[A] = import DerivedShowPretty.given summonInline[DerivedShowPretty[A]].instance + private def fromToString[A]: ShowPretty[A] = + _.toString :: Nil + + // These instances support singleton types unlike the instances in Cats' core. + given boolean[A <: Boolean]: DerivedShowPretty[A] = fromToString + given byte[A <: Byte]: DerivedShowPretty[A] = fromToString + given short[A <: Short]: DerivedShowPretty[A] = fromToString + given int[A <: Int]: DerivedShowPretty[A] = fromToString + given long[A <: Long]: DerivedShowPretty[A] = fromToString + given float[A <: Float]: DerivedShowPretty[A] = fromToString + given double[A <: Double]: DerivedShowPretty[A] = fromToString + given char[A <: Char]: DerivedShowPretty[A] = fromToString + given string[A <: String]: DerivedShowPretty[A] = fromToString + given symbol[A <: Symbol]: DerivedShowPretty[A] = fromToString + given [A](using inst: K0.ProductInstances[Or, A], labelling: Labelling[A]): DerivedShowPretty[A] = new Product[A] {} diff --git a/core/src/test/scala-2/cats/derived/adtdefns.scala b/core/src/test/scala-2/cats/derived/adtdefns.scala index 9c678d9b..b3f53b6b 100644 --- a/core/src/test/scala-2/cats/derived/adtdefns.scala +++ b/core/src/test/scala-2/cats/derived/adtdefns.scala @@ -19,6 +19,7 @@ package cats.derived import cats.{Eq, Eval} import org.scalacheck.rng.Seed import org.scalacheck.{Arbitrary, Cogen, Gen} +import shapeless.Witness import scala.annotation.tailrec @@ -279,6 +280,27 @@ object TestDefns { final case class ListField(a: String, b: List[ListFieldChild]) final case class ListFieldChild(c: Int) + final case class Singletons[A]( + value: A, + str: Singletons.str.T = Singletons.str.value, + chr: Singletons.chr.T = Singletons.chr.value, + lng: Singletons.lng.T = Singletons.lng.value, + dbl: Singletons.dbl.T = Singletons.dbl.value + ) + + object Singletons { + val str = Witness("Scala") + val chr = Witness('+') + val lng = Witness(42L) + val dbl = Witness(3.14) + + implicit def arbitrary[A: Arbitrary]: Arbitrary[Singletons[A]] = + Arbitrary(Arbitrary.arbitrary[A].map(Singletons(_))) + + implicit def cogen[A: Cogen]: Cogen[Singletons[A]] = + Cogen[Option[(A, String, Char, Long, Double)]].contramap(unapply) + } + final case class Large( bar1: String, bar2: Int, @@ -470,4 +492,7 @@ object TestEqInstances { implicit def eqCaseClassWOption[A: Eq]: Eq[CaseClassWOption[A]] = Eq.by(_.value) + + implicit def eqSingletons[A: Eq]: Eq[Singletons[A]] = + Eq.by(_.value) } diff --git a/core/src/test/scala-2/cats/derived/eq.scala b/core/src/test/scala-2/cats/derived/eq.scala index 6ab235bf..04e1fe41 100644 --- a/core/src/test/scala-2/cats/derived/eq.scala +++ b/core/src/test/scala-2/cats/derived/eq.scala @@ -30,7 +30,8 @@ class EqSuite extends KittensSuite { outer: Eq[Outer], interleaved: Eq[Interleaved[Int]], tree: Eq[Tree[Int]], - recursive: Eq[Recursive] + recursive: Eq[Recursive], + singletons: Eq[Singletons[Int]] ): Unit = { checkAll(s"$context.Eq[Foo]]", EqTests[Foo].eqv) checkAll(s"$context.Eq[IList[Int]]", EqTests[IList[Int]].eqv) @@ -39,6 +40,7 @@ class EqSuite extends KittensSuite { checkAll(s"$context.Eq[Interleaved[Int]]", EqTests[Interleaved[Int]].eqv) checkAll(s"$context.Eq[Tree[Int]]", EqTests[Tree[Int]].eqv) checkAll(s"$context.Eq[Recursive]", EqTests[Recursive].eqv) + checkAll(s"$context.Eq[Singletons[Int]]", EqTests[Singletons[Int]].eqv) checkAll(s"$context.Eq is Serializable", SerializableTests.serializable(Eq[Tree[Int]])) } @@ -69,5 +71,6 @@ object EqSuite { implicit val interleaved: Eq[Interleaved[Int]] = semiauto.eq implicit val tree: Eq[Tree[Int]] = semiauto.eq implicit val recursive: Eq[Recursive] = semiauto.eq + implicit val singletons: Eq[Singletons[Int]] = semiauto.eq } } diff --git a/core/src/test/scala-2/cats/derived/foldable.scala b/core/src/test/scala-2/cats/derived/foldable.scala index 42aaf61b..536f49c2 100644 --- a/core/src/test/scala-2/cats/derived/foldable.scala +++ b/core/src/test/scala-2/cats/derived/foldable.scala @@ -16,6 +16,7 @@ package cats package derived + import cats.laws.discipline.{FoldableTests, SerializableTests} import org.scalacheck.Arbitrary @@ -32,6 +33,7 @@ class FoldableSuite extends KittensSuite { listSnoc: Foldable[ListSnoc], andChar: Foldable[AndChar], interleaved: Foldable[Interleaved], + singletons: Foldable[Singletons], boxNel: Foldable[BoxNel] ): Unit = { checkAll(s"$context.Foldable[IList]", FoldableTests[IList].foldable[Int, Long]) @@ -41,6 +43,7 @@ class FoldableSuite extends KittensSuite { checkAll(s"$context.Foldable[ListSnoc]", FoldableTests[ListSnoc].foldable[Int, Long]) checkAll(s"$context.Foldable[AndChar]", FoldableTests[AndChar].foldable[Int, Long]) checkAll(s"$context.Foldable[Interleaved]", FoldableTests[Interleaved].foldable[Int, Long]) + checkAll(s"$context.Foldable[Singletons]", FoldableTests[Singletons].foldable[Int, Long]) checkAll(s"$context.Foldable[BoxNel]", FoldableTests[BoxNel].foldable[Int, Long]) checkAll(s"$context.Foldable is Serializable", SerializableTests.serializable(Foldable[Tree])) @@ -103,6 +106,7 @@ object FoldableSuite { implicit val listSnoc: Foldable[ListSnoc] = semiauto.foldable implicit val andChar: Foldable[AndChar] = semiauto.foldable implicit val interleaved: Foldable[Interleaved] = semiauto.foldable + implicit val singletons: Foldable[Singletons] = semiauto.foldable implicit val boxNel: Foldable[BoxNel] = semiauto.foldable } diff --git a/core/src/test/scala-2/cats/derived/functor.scala b/core/src/test/scala-2/cats/derived/functor.scala index f7072ac0..6ad4dec1 100644 --- a/core/src/test/scala-2/cats/derived/functor.scala +++ b/core/src/test/scala-2/cats/derived/functor.scala @@ -35,7 +35,8 @@ class FunctorSuite extends KittensSuite { listSnoc: Functor[ListSnoc], andChar: Functor[AndChar], interleaved: Functor[Interleaved], - nestedPred: Functor[NestedPred] + nestedPred: Functor[NestedPred], + singletons: Functor[Singletons] ): Unit = { checkAll(s"$context.Functor[IList]", FunctorTests[IList].functor[Int, String, Long]) checkAll(s"$context.Functor[Tree]", FunctorTests[Tree].functor[Int, String, Long]) @@ -45,6 +46,7 @@ class FunctorSuite extends KittensSuite { checkAll(s"$context.Functor[AndChar]", FunctorTests[AndChar].functor[Int, String, Long]) checkAll(s"$context.Functor[Interleaved]", FunctorTests[Interleaved].functor[Int, String, Long]) checkAll(s"$context.Functor[NestedPred]", FunctorTests[NestedPred].functor[Boolean, Int, Boolean]) + checkAll(s"$context.Functor[Singletons]", FunctorTests[Singletons].functor[Boolean, Int, Boolean]) checkAll(s"$context.Functor is Serializable", SerializableTests.serializable(Functor[Tree])) test(s"$context.Functor.map is stack safe") { @@ -93,5 +95,6 @@ object FunctorSuite { implicit val andChar: Functor[AndChar] = semiauto.functor implicit val interleaved: Functor[Interleaved] = semiauto.functor implicit val nestedPred: Functor[NestedPred] = semiauto.functor + implicit val singletons: Functor[Singletons] = semiauto.functor } } diff --git a/core/src/test/scala-2/cats/derived/hash.scala b/core/src/test/scala-2/cats/derived/hash.scala index 4e74002c..3fb1295a 100644 --- a/core/src/test/scala-2/cats/derived/hash.scala +++ b/core/src/test/scala-2/cats/derived/hash.scala @@ -13,15 +13,16 @@ class HashSuite extends KittensSuite { outer: Hash[Outer], interleaved: Hash[Interleaved[Int]], tree: Hash[Tree[Int]], - recursive: Hash[Recursive] + recursive: Hash[Recursive], + singletons: Hash[Singletons[Int]] ): Unit = { checkAll(s"$context.Hash[IList[Int]]", HashTests[IList[Int]].hash) checkAll(s"$context.Hash[Inner]", HashTests[Inner].hash) checkAll(s"$context.Hash[Outer]", HashTests[Outer].hash) - // FIXME: typelevel/cats#2878 - // checkAll(s"$context.Hash[Interleaved[Int]]", HashTests[Interleaved[Int]].hash) + checkAll(s"$context.Hash[Interleaved[Int]]", HashTests[Interleaved[Int]].hash) checkAll(s"$context.Hash[Tree[Int]]", HashTests[Tree[Int]].hash) checkAll(s"$context.Hash[Recursive]", HashTests[Recursive].hash) + checkAll(s"$context.Hash[Singletons[Int]", HashTests[Singletons[Int]].hash) checkAll(s"$context.Hash is Serializable", SerializableTests.serializable(Hash[Tree[Int]])) } @@ -51,5 +52,6 @@ object HashSuite { implicit val interleaved: Hash[Interleaved[Int]] = semiauto.hash implicit val tree: Hash[Tree[Int]] = semiauto.hash implicit val recursive: Hash[Recursive] = semiauto.hash + implicit val singletons: Hash[Singletons[Int]] = semiauto.hash } } diff --git a/core/src/test/scala-2/cats/derived/invariant.scala b/core/src/test/scala-2/cats/derived/invariant.scala index c0e588d6..8bbe4f96 100644 --- a/core/src/test/scala-2/cats/derived/invariant.scala +++ b/core/src/test/scala-2/cats/derived/invariant.scala @@ -16,10 +16,10 @@ package cats package derived + import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ -import cats.laws.discipline._ class InvariantSuite extends KittensSuite { import InvariantSuite._ @@ -28,21 +28,23 @@ class InvariantSuite extends KittensSuite { def testInvariant(context: String)(implicit tree: Invariant[TreeF], - genadt: Invariant[GenericAdtF], - ListFToInt: Invariant[ListFToInt], + genericAdtF: Invariant[GenericAdtF], + listSnocF: Invariant[ListSnocF], listSnoc: Invariant[ListSnoc], - interleaved: Invariant[InterleavedF], + interleavedF: Invariant[InterleavedF], andCharF: Invariant[AndCharF], bivariant: Invariant[Bivariant], - ilist: Invariant[IList] + ilist: Invariant[IList], + singletons: Invariant[Singletons] ): Unit = { checkAll(s"$context.Invariant[TreeF]", InvariantTests[TreeF].invariant[MiniInt, String, Boolean]) - checkAll(s"$context.Invariant[GenAdtF]", InvariantTests[GenericAdtF].invariant[MiniInt, String, Boolean]) + checkAll(s"$context.Invariant[GenericAdtF]", InvariantTests[GenericAdtF].invariant[MiniInt, String, Boolean]) + checkAll(s"$context.Invariant[ListSnocF]", InvariantTests[ListSnocF].invariant[MiniInt, String, Boolean]) checkAll(s"$context.Invariant[InterleavedF]", InvariantTests[InterleavedF].invariant[MiniInt, String, Boolean]) checkAll(s"$context.Invariant[AndCharF]", InvariantTests[AndCharF].invariant[MiniInt, String, Boolean]) checkAll(s"$context.Invariant[ListSnoc", InvariantTests[ListSnoc].invariant[MiniInt, String, Boolean]) checkAll(s"$context.Invariant[Bivariant]", InvariantTests[Bivariant].invariant[MiniInt, String, Boolean]) - + checkAll(s"$context.Invariant[Singletons]", InvariantTests[Singletons].invariant[MiniInt, String, Boolean]) checkAll(s"$context.Invariant is Serializable", SerializableTests.serializable(Invariant[TreeF])) test(s"$context.Invariant.imap is stack safe") { @@ -78,20 +80,21 @@ object InvariantSuite { type ListSnoc[A] = List[Snoc[A]] type GenericAdtF[A] = GenericAdt[A => Boolean] - type ListFToInt[A] = List[Snoc[A => Int]] + type ListSnocF[A] = List[Snoc[A => Int]] type InterleavedF[A] = Interleaved[A => Boolean] type AndCharF[A] = (A => Boolean, Char) type TreeF[A] = Tree[A => Boolean] object semiInstances { - implicit val gadt: Invariant[GenericAdtF] = semiauto.invariant[GenericAdtF] - implicit val listSnocendo: Invariant[ListFToInt] = semiauto.invariant[ListFToInt] - implicit val interleaveF: Invariant[InterleavedF] = semiauto.invariant[InterleavedF] - implicit val andCharF: Invariant[AndCharF] = semiauto.invariant[AndCharF] - implicit val treeF: Invariant[TreeF] = semiauto.invariant[TreeF] - implicit val pred: Invariant[Pred] = semiauto.invariant[Pred] - implicit val snoc: Invariant[ListSnoc] = semiauto.invariant[ListSnoc] - implicit val bivariant: Invariant[Bivariant] = semiauto.invariant[Bivariant] - implicit val ilist: Invariant[IList] = semiauto.invariant[IList] + implicit val genericAdtF: Invariant[GenericAdtF] = semiauto.invariant + implicit val listSnocF: Invariant[ListSnocF] = semiauto.invariant + implicit val interleavedF: Invariant[InterleavedF] = semiauto.invariant + implicit val andCharF: Invariant[AndCharF] = semiauto.invariant + implicit val treeF: Invariant[TreeF] = semiauto.invariant + implicit val pred: Invariant[Pred] = semiauto.invariant + implicit val snoc: Invariant[ListSnoc] = semiauto.invariant + implicit val bivariant: Invariant[Bivariant] = semiauto.invariant + implicit val ilist: Invariant[IList] = semiauto.invariant + implicit val singletons: Invariant[Singletons] = semiauto.invariant } } diff --git a/core/src/test/scala-2/cats/derived/nonEmptyTraverse.scala b/core/src/test/scala-2/cats/derived/nonEmptyTraverse.scala index 7ac32de8..7ecfb5b8 100644 --- a/core/src/test/scala-2/cats/derived/nonEmptyTraverse.scala +++ b/core/src/test/scala-2/cats/derived/nonEmptyTraverse.scala @@ -32,7 +32,8 @@ class NonEmptyTraverseSuite extends KittensSuite { nelSCons: NonEmptyTraverse[NelSCons], nelAndOne: NonEmptyTraverse[NelAndOne], listAndNel: NonEmptyTraverse[ListAndNel], - interleaved: NonEmptyTraverse[Interleaved] + interleaved: NonEmptyTraverse[Interleaved], + singletons: NonEmptyTraverse[Singletons] ): Unit = { checkAll( @@ -65,6 +66,11 @@ class NonEmptyTraverseSuite extends KittensSuite { NonEmptyTraverseTests[Interleaved].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option] ) + checkAll( + s"$context.NonEmptyTraverse[Singletons]", + NonEmptyTraverseTests[Singletons].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option] + ) + checkAll( s"$context.NonEmptyTraverse is Serializable", SerializableTests.serializable(NonEmptyTraverse[Tree]) @@ -112,5 +118,6 @@ object NonEmptyTraverseSuite { implicit val nelAndOne: NonEmptyTraverse[NelAndOne] = semiauto.nonEmptyTraverse implicit val listAndNel: NonEmptyTraverse[ListAndNel] = semiauto.nonEmptyTraverse implicit val interleaved: NonEmptyTraverse[Interleaved] = semiauto.nonEmptyTraverse + implicit val singletons: NonEmptyTraverse[Singletons] = semiauto.nonEmptyTraverse } } diff --git a/core/src/test/scala-2/cats/derived/order.scala b/core/src/test/scala-2/cats/derived/order.scala index 5eef007a..39a1a566 100644 --- a/core/src/test/scala-2/cats/derived/order.scala +++ b/core/src/test/scala-2/cats/derived/order.scala @@ -28,12 +28,14 @@ class OrderSuite extends KittensSuite { outer: Order[Outer], interleaved: Order[Interleaved[Int]], recursive: Order[Recursive], + singletons: Order[Singletons[Int]], genericAdt: Order[GenericAdt[Int]] ): Unit = { checkAll(s"$context.Order[Inner]", OrderTests[Inner].order) checkAll(s"$context.Order[Outer]", OrderTests[Outer].order) checkAll(s"$context.Order[Interleaved[Int]]", OrderTests[Interleaved[Int]].order) checkAll(s"$context.Order[Recursive]", OrderTests[Recursive].order) + checkAll(s"$context.Order[Singletons[Int]]", OrderTests[Singletons[Int]].order) checkAll(s"$context.Order[GenericAdt[Int]]", OrderTests[GenericAdt[Int]].order) checkAll(s"$context.Order is Serializable", SerializableTests.serializable(Order[Interleaved[Int]])) } @@ -62,6 +64,7 @@ object OrderSuite { implicit val outer: Order[Outer] = semiauto.order implicit val interleaved: Order[Interleaved[Int]] = semiauto.order implicit val recursive: Order[Recursive] = semiauto.order + implicit val singletons: Order[Singletons[Int]] = semiauto.order implicit val genericAdt: Order[GenericAdt[Int]] = semiauto.order } } diff --git a/core/src/test/scala-2/cats/derived/partialOrder.scala b/core/src/test/scala-2/cats/derived/partialOrder.scala index e6b2c335..8c7d39d0 100644 --- a/core/src/test/scala-2/cats/derived/partialOrder.scala +++ b/core/src/test/scala-2/cats/derived/partialOrder.scala @@ -16,6 +16,7 @@ package cats package derived + import cats.kernel.laws.discipline.{PartialOrderTests, SerializableTests} import org.scalacheck.{Arbitrary, Cogen} @@ -30,6 +31,7 @@ class PartialOrderSuite extends KittensSuite { interleaved: PartialOrder[Interleaved[Int]], tree: PartialOrder[Tree[Int]], recursive: PartialOrder[Recursive], + singletons: PartialOrder[Singletons[Int]], boxKeyValue: PartialOrder[Box[KeyValue]] ): Unit = { checkAll(s"$context.PartialOrder[IList[Int]]", PartialOrderTests[IList[Int]].partialOrder) @@ -38,8 +40,9 @@ class PartialOrderSuite extends KittensSuite { 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[Singletons[Int]]", PartialOrderTests[Singletons[Int]].partialOrder) checkAll(s"$context.PartialOrder[Box[KeyValue]]", PartialOrderTests[Box[KeyValue]].partialOrder) - checkAll(s"$context.PartialOrder is Serialiable", SerializableTests.serializable(PartialOrder[Tree[Int]])) + checkAll(s"$context.PartialOrder is Serializable", SerializableTests.serializable(PartialOrder[Tree[Int]])) test(s"$context.PartialOrder respects existing instances") { val x = Box(KeyValue("red", 1)) @@ -76,6 +79,7 @@ object PartialOrderSuite { 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 singletons: PartialOrder[Singletons[Int]] = semiauto.partialOrder implicit val boxKeyValue: PartialOrder[Box[KeyValue]] = semiauto.partialOrder } diff --git a/core/src/test/scala-2/cats/derived/pure.scala b/core/src/test/scala-2/cats/derived/pure.scala index 4b3c5d75..b711eb5c 100644 --- a/core/src/test/scala-2/cats/derived/pure.scala +++ b/core/src/test/scala-2/cats/derived/pure.scala @@ -32,6 +32,7 @@ class PureSuite extends KittensSuite { caseClassWOption: Pure[CaseClassWOption], nelOption: Pure[NelOption], interleaved: Pure[Interleaved], + singletons: Pure[Singletons], boxColor: Pure[BoxColor] ): Unit = { test(s"$context.Pure[LOption]")(assert(lOption.pure(42) == Some(42) :: Nil)) @@ -39,6 +40,7 @@ class PureSuite extends KittensSuite { test(s"$context.Pure[CaseClassWOption]")(assert(caseClassWOption.pure(3.14) == CaseClassWOption(Some(3.14)))) test(s"$context.Pure[NelOption]")(assert(nelOption.pure(42) == NonEmptyList.of(Some(42)))) test(s"$context.Pure[Interleaved]")(assert(interleaved.pure('x') == Interleaved(0, 'x', 0, 'x' :: Nil, ""))) + test(s"$context.Pure[Singletons]")(assert(singletons.pure('x') == Singletons('x'))) test(s"$context.Pure respects existing instances")(assert(boxColor.pure(()) == Box(Color(255, 255, 255)))) checkAll(s"$context.Pure is Serializable", SerializableTests.serializable(Pure[Interleaved])) } @@ -79,6 +81,7 @@ object PureSuite { implicit val caseClassWOption: Pure[CaseClassWOption] = semiauto.pure implicit val nelOption: Pure[NelOption] = semiauto.pure implicit val interleaved: Pure[Interleaved] = semiauto.pure + implicit val singletons: Pure[Singletons] = semiauto.pure implicit val boxColor: Pure[BoxColor] = semiauto.pure } diff --git a/core/src/test/scala-2/cats/derived/reducible.scala b/core/src/test/scala-2/cats/derived/reducible.scala index 748d4d88..9b5b5e38 100644 --- a/core/src/test/scala-2/cats/derived/reducible.scala +++ b/core/src/test/scala-2/cats/derived/reducible.scala @@ -34,6 +34,7 @@ class ReducibleSuite extends KittensSuite { nelAndOne: Reducible[NelAndOne], listAndNel: Reducible[ListAndNel], interleaved: Reducible[Interleaved], + singletons: Reducible[Singletons], boxZipper: Reducible[BoxZipper] ): Unit = { checkAll(s"$context.Reducible[ICons]", ReducibleTests[ICons].reducible[Option, Int, Long]) @@ -42,6 +43,7 @@ class ReducibleSuite extends KittensSuite { checkAll(s"$context.Reducible[NelAndOne]", ReducibleTests[NelAndOne].reducible[Option, Int, Long]) checkAll(s"$context.Reducible[ListAndNel]", ReducibleTests[ListAndNel].reducible[Option, Int, Long]) checkAll(s"$context.Reducible[Interleaved]", ReducibleTests[Interleaved].reducible[Option, Int, Long]) + checkAll(s"$context.Reducible[Singletons]", ReducibleTests[Singletons].reducible[Option, Int, Long]) checkAll(s"$context.Reducible[BoxZipper]", ReducibleTests[BoxZipper].reducible[Option, Int, Long]) checkAll(s"$context.Reducible is Serializable", SerializableTests.serializable(Reducible[Tree])) @@ -103,6 +105,7 @@ object ReducibleSuite { implicit val nelAndOne: Reducible[NelAndOne] = semiauto.reducible implicit val listAndNel: Reducible[ListAndNel] = semiauto.reducible implicit val interleaved: Reducible[Interleaved] = semiauto.reducible + implicit val singletons: Reducible[Singletons] = semiauto.reducible implicit val boxZipper: Reducible[BoxZipper] = semiauto.reducible } diff --git a/core/src/test/scala-2/cats/derived/show.scala b/core/src/test/scala-2/cats/derived/show.scala index 726eea4c..643c02d8 100644 --- a/core/src/test/scala-2/cats/derived/show.scala +++ b/core/src/test/scala-2/cats/derived/show.scala @@ -16,6 +16,7 @@ class ShowSuite extends KittensSuite { listField: Show[ListField], interleaved: Show[Interleaved[Int]], tree: Show[Tree[Int]], + singletons: Show[Singletons[Int]], boxBogus: Show[Box[Bogus]] ): Unit = { checkAll(s"$context.Show is Serializable", SerializableTests.serializable(Show[IntTree])) @@ -71,6 +72,12 @@ class ShowSuite extends KittensSuite { assert(value.show == shown) } + test(s"$context.Show[Singletons[Int]]") { + val value = Singletons[Int](313) + val shown = "Singletons(value = 313, str = Scala, chr = +, lng = 42, dbl = 3.14)" + assert(value.show == shown) + } + test(s"$context.Show respects existing instances") { val value = Box(Bogus(42)) val shown = "Box(content = Blah)" @@ -116,6 +123,7 @@ object ShowSuite { implicit val listField: Show[ListField] = semiauto.show implicit val interleaved: Show[Interleaved[Int]] = semiauto.show implicit val tree: Show[Tree[Int]] = semiauto.show + implicit val singletons: Show[Singletons[Int]] = semiauto.show implicit val boxBogus: Show[Box[Bogus]] = semiauto.show } } diff --git a/core/src/test/scala-2/cats/derived/showPretty.scala b/core/src/test/scala-2/cats/derived/showPretty.scala index a49b1ac8..4c4ed5df 100644 --- a/core/src/test/scala-2/cats/derived/showPretty.scala +++ b/core/src/test/scala-2/cats/derived/showPretty.scala @@ -16,6 +16,7 @@ class ShowPrettySuite extends KittensSuite { listField: ShowPretty[ListField], interleaved: ShowPretty[Interleaved[Int]], tree: ShowPretty[Tree[Int]], + singletons: ShowPretty[Singletons[Int]], boxBogus: ShowPretty[Box[Bogus]] ): Unit = { checkAll(s"$context.ShowPretty is Serializable", SerializableTests.serializable(ShowPretty[IntTree])) @@ -152,6 +153,21 @@ class ShowPrettySuite extends KittensSuite { assert(value.show == pretty) } + test(s"$context.ShowPretty[Singletons[Int]]") { + val value = Singletons[Int](313) + val pretty = """ + |Singletons( + | value = 313, + | str = Scala, + | chr = +, + | lng = 42, + | dbl = 3.14 + |) + """.stripMargin.trim + + assert(value.show == pretty) + } + test(s"$context.ShowPretty respects existing instances") { val value = Box(Bogus(42)) val pretty = """ @@ -202,6 +218,7 @@ object ShowPrettySuite { implicit val listField: ShowPretty[ListField] = semiauto.showPretty implicit val interleaved: ShowPretty[Interleaved[Int]] = semiauto.showPretty implicit val tree: ShowPretty[Tree[Int]] = semiauto.showPretty + implicit val singletons: ShowPretty[Singletons[Int]] = semiauto.showPretty implicit val boxBogus: ShowPretty[Box[Bogus]] = semiauto.showPretty } } diff --git a/core/src/test/scala-2/cats/derived/traverse.scala b/core/src/test/scala-2/cats/derived/traverse.scala index 4cc45f69..dd6c7d7a 100644 --- a/core/src/test/scala-2/cats/derived/traverse.scala +++ b/core/src/test/scala-2/cats/derived/traverse.scala @@ -1,5 +1,6 @@ package cats package derived + import cats.laws.discipline.{SerializableTests, TraverseTests} class TraverseSuite extends KittensSuite { @@ -14,7 +15,8 @@ class TraverseSuite extends KittensSuite { optList: Traverse[OptList], listSnoc: Traverse[ListSnoc], andChar: Traverse[AndChar], - interleaved: Traverse[Interleaved] + interleaved: Traverse[Interleaved], + singletons: Traverse[Singletons] ): Unit = { checkAll(s"$context.Traverse[IList]", TraverseTests[IList].traverse[Int, Double, String, Long, Option, Option]) checkAll(s"$context.Traverse[Tree]", TraverseTests[Tree].traverse[Int, Double, String, Long, Option, Option]) @@ -32,6 +34,10 @@ class TraverseSuite extends KittensSuite { s"$context.Traverse[Interleaved]", TraverseTests[Interleaved].traverse[Int, Double, String, Long, Option, Option] ) + checkAll( + s"$context.Traverse[Singletons]", + TraverseTests[Singletons].traverse[Int, Double, String, Long, Option, Option] + ) checkAll(s"$context.Traverse is Serializable", SerializableTests.serializable(Traverse[Tree])) val n = 10000 @@ -94,5 +100,6 @@ object TraverseSuite { implicit val listSnoc: Traverse[ListSnoc] = semiauto.traverse implicit val andChar: Traverse[AndChar] = semiauto.traverse implicit val interleaved: Traverse[Interleaved] = semiauto.traverse + implicit val singletons: Traverse[Singletons] = semiauto.traverse } } diff --git a/core/src/test/scala-3/cats/derived/ADTs.scala b/core/src/test/scala-3/cats/derived/ADTs.scala index 7dc277ec..653cfa0a 100644 --- a/core/src/test/scala-3/cats/derived/ADTs.scala +++ b/core/src/test/scala-3/cats/derived/ADTs.scala @@ -102,9 +102,6 @@ object ADTs: yield ComplexProduct(lbl, set, fns, Eval.now(opt))) final case class Box[+A](content: A) - object Box: - given [A: Arbitrary]: Arbitrary[Box[A]] = Arbitrary(Arbitrary.arbitrary[A].map(apply)) - given [A: Cogen]: Cogen[Box[A]] = Cogen[A].contramap(_.content) final case class Recursive(i: Int, is: Option[Recursive]) object Recursive extends ((Int, Option[Recursive]) => Recursive): @@ -127,18 +124,8 @@ object ADTs: object Interleaved: def empty[T](t: T): Interleaved[T] = Interleaved(0, t, 0, Vector.empty, "") - given [T: Arbitrary]: Arbitrary[Interleaved[T]] = - Arbitrary(Arbitrary.arbitrary[(Int, T, Long, Vector[T], String)].map(apply)) - given [T: Cogen]: Cogen[Interleaved[T]] = - Cogen[(Int, T, Long, Vector[T], String)].contramap(x => (x.i, x.t, x.l, x.tt, x.s)) case class Bivariant[A](run: A => Boolean, store: A) - object Bivariant: - given [A: Arbitrary]: Arbitrary[Bivariant[A]] = Arbitrary(for - a <- Arbitrary.arbitrary[A] - f <- Arbitrary.arbitrary[Boolean].map(Function.const[Boolean, A]) - yield Bivariant[A](f, a)) - case class Pred[A](run: A => Boolean) sealed trait IList[A] @@ -213,33 +200,11 @@ object ADTs: cogen final case class Foo(i: Int, b: Option[String]) - object Foo: - given Cogen[Foo] = Cogen[Int].contramap(_.i) - given Arbitrary[Foo] = Arbitrary(for - i <- Arbitrary.arbitrary[Int] - b <- Arbitrary.arbitrary[Option[String]] - yield Foo(i, b)) - final case class CommutativeFoo(i: Int, b: Option[Long]) - object CommutativeFoo: - given Cogen[CommutativeFoo] = - Cogen[(Int, Option[Long])].contramap(x => (x.i, x.b)) - given Arbitrary[CommutativeFoo] = Arbitrary(for - i <- Arbitrary.arbitrary[Int] - b <- Arbitrary.arbitrary[Option[Long]] - yield CommutativeFoo(i, b)) case class Inner(i: Int) case class Outer(in: Inner) - object Inner: - given Arbitrary[Inner] = Arbitrary(Arbitrary.arbitrary[Int].map(apply)) - given Cogen[Inner] = Cogen[Int].contramap(_.i) - - object Outer: - given Arbitrary[Outer] = Arbitrary(Arbitrary.arbitrary[Inner].map(apply)) - given Cogen[Outer] = Cogen[Inner].contramap(_.in) - sealed trait IntTree final case class IntLeaf(t: Int) extends IntTree final case class IntNode(l: IntTree, r: IntTree) extends IntTree @@ -256,9 +221,6 @@ object ADTs: Cogen[Option[A]].contramap { case GenericAdtCase(value) => value } final case class CaseClassWOption[A](value: Option[A]) - object CaseClassWOption: - given [A: Arbitrary]: Arbitrary[CaseClassWOption[A]] = - Arbitrary(Arbitrary.arbitrary[Option[A]].map(apply)) final case class First(value: String) final case class Second(value: String) @@ -272,6 +234,8 @@ object ADTs: final case class ListField(a: String, b: List[ListFieldChild]) final case class ListFieldChild(c: Int) + final case class Singletons[A](value: A, str: "Scala" = "Scala", lng: 42L = 42L, dbl: 3.14 = 3.14) + enum Many[+A] derives Eq: case Naught case More(value: A, rest: Many[A]) @@ -311,12 +275,10 @@ object ADTs: trait EqInstances: import ADTs.* - given [T: Eq]: Eq[ComplexProduct[T]] = (x, y) => - x.lbl == y.lbl && x.set === y.set && x.fns.map(_()) === y.fns.map(_()) && x.opt === y.opt - - given [A: Eq]: Eq[Box[A]] = Eq.by(_.content) given Eq[Recursive] = Eq.fromUniversalEquals - given [T: Eq]: Eq[Interleaved[T]] = Eq.by(i => (i.i, i.t, i.l, i.tt, i.s)) + given [A: Eq]: Eq[ICons[A]] = Eq.by(identity[IList[A]]) + given [A: Eq]: Eq[SCons[A]] = Eq.by(identity[Snoc[A]]) + given [A: Eq]: Eq[GenericAdt[A]] = Eq.by { case GenericAdtCase(v) => v } given [A: Eq]: Eq[IList[A]] with @tailrec final def eqv(x: IList[A], y: IList[A]): Boolean = (x, y) match @@ -330,49 +292,35 @@ object ADTs: case (SNil(), SNil()) => true case _ => false - given [A: Eq]: Eq[ICons[A]] = Eq.by(identity[IList[A]]) - given [A: Eq]: Eq[SCons[A]] = Eq.by(identity[Snoc[A]]) - given [A: Eq]: Eq[Tree[A]] with def eqv(x: Tree[A], y: Tree[A]): Boolean = (x, y) match case (Leaf(vx), Leaf(vy)) => vx === vy case (Node(lx, rx), Node(ly, ry)) => eqv(lx, ly) && eqv(rx, ry) case _ => false - given [A: Eq]: Eq[Bivariant[A]] = { case (Bivariant(runX, storeX), Bivariant(runY, storeY)) => - storeX === storeY && runX(storeX) == runY(storeY) - } - - given Eq[Foo] = Eq.fromUniversalEquals - given Eq[CommutativeFoo] = Eq.fromUniversalEquals - given [A: Eq]: Eq[GenericAdt[A]] = Eq.by { case GenericAdtCase(v) => v } - given [A: Eq]: Eq[CaseClassWOption[A]] = Eq.by(_.value) - given Eq[Inner] = Eq.fromUniversalEquals - given Eq[Outer] = Eq.fromUniversalEquals + given [A: Eq]: Eq[Bivariant[A]] = + case (Bivariant(runX, storeX), Bivariant(runY, storeY)) => + storeX === storeY && runX(storeX) == runY(storeY) - given Eq[EnumK0] = { + given Eq[EnumK0] = case (EnumK0.LeafS(s1), EnumK0.LeafS(s2)) => s1 === s2 case (EnumK0.LeafI(i1), EnumK0.LeafI(i2)) => i1 === i2 case _ => false - } - given [A: Eq]: Eq[EnumK1[A]] = { + given [A: Eq]: Eq[EnumK1[A]] = case (EnumK1.Leaf(v1), EnumK1.Leaf(v2)) => v1 === v2 case (EnumK1.Rec(l1, r1), EnumK1.Rec(l2, r2)) => l1 === l2 && r1 === r2 case _ => false - } - given [A](using Eq[A => Unit]): Eq[EnumK1Contra[A]] = { + given [A](using Eq[A => Unit]): Eq[EnumK1Contra[A]] = case (EnumK1Contra.Leaf(v1), EnumK1Contra.Leaf(v2)) => v1 === v2 case (EnumK1Contra.Rec(l1, r1), EnumK1Contra.Rec(l2, r2)) => l1 === l2 && r1 === r2 case _ => false - } - given [A: Eq](using Eq[A => Unit]): Eq[EnumK1Inv[A]] = { + given [A: Eq](using Eq[A => Unit]): Eq[EnumK1Inv[A]] = case (EnumK1Inv.Leaf(cov1, contra1), EnumK1Inv.Leaf(cov2, contra2)) => cov1 === cov2 && contra1 === contra2 case (EnumK1Inv.Rec(l1, r1), EnumK1Inv.Rec(l2, r2)) => l1 === l2 && r1 === r2 case _ => false - } end EqInstances end ADTs diff --git a/core/src/test/scala-3/cats/derived/EqSuite.scala b/core/src/test/scala-3/cats/derived/EqSuite.scala index bce4a3ee..87eb0108 100644 --- a/core/src/test/scala-3/cats/derived/EqSuite.scala +++ b/core/src/test/scala-3/cats/derived/EqSuite.scala @@ -35,19 +35,18 @@ class EqSuite extends KittensSuite.WithoutEq: checkAll(s"$instance[Interleaved[Int]]", tests[Interleaved[Int]].eqv) checkAll(s"$instance[Tree[Int]]", tests[Tree[Int]].eqv) checkAll(s"$instance[Recursive]", tests[Recursive].eqv) + checkAll(s"$instance[Singletons[Int]]", tests[Singletons[Int]].eqv) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Eq[Foo]])) - locally { + locally: import auto.eq.given validate("auto.eq") - } - locally { + locally: import semiInstances.given validate("semiauto.eq") - } - locally { + locally: import derivedInstances.* val instance = "derived.eq" checkAll(s"$instance[Foo]]", tests[Foo].eqv) @@ -57,8 +56,8 @@ class EqSuite extends KittensSuite.WithoutEq: checkAll(s"$instance[Interleaved[Int]]", tests[Interleaved[Int]].eqv) checkAll(s"$instance[Tree[Int]]", tests[Tree[Int]].eqv) checkAll(s"$instance[Recursive]", tests[Recursive].eqv) + checkAll(s"$instance[Singletons[Int]]", tests[Singletons[Int]].eqv) checkAll(s"$instance is Serializable", SerializableTests.serializable(Eq[Foo])) - } end EqSuite @@ -73,6 +72,7 @@ object EqSuite: given Eq[Interleaved[Int]] = semiauto.eq given Eq[Tree[Int]] = semiauto.eq given Eq[Recursive] = semiauto.eq + given Eq[Singletons[Int]] = semiauto.eq object derivedInstances: case class Foo(x: ADTs.Foo) derives Eq @@ -82,5 +82,6 @@ object EqSuite: case class Interleaved[A](x: ADTs.Interleaved[A]) derives Eq case class Tree[A](x: ADTs.Tree[A]) derives Eq case class Recursive(x: ADTs.Recursive) derives Eq + case class Singletons[A](x: ADTs.Singletons[A]) derives Eq end EqSuite diff --git a/core/src/test/scala-3/cats/derived/FoldableSuite.scala b/core/src/test/scala-3/cats/derived/FoldableSuite.scala index 7bef2b80..b4fd85d7 100644 --- a/core/src/test/scala-3/cats/derived/FoldableSuite.scala +++ b/core/src/test/scala-3/cats/derived/FoldableSuite.scala @@ -41,19 +41,18 @@ class FoldableSuite extends KittensSuite: checkAll(s"$instance[Many]", tests[Many].foldable[Int, Long]) checkAll(s"$instance[AtMostOne]", tests[AtMostOne].foldable[Int, Long]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].foldable[Int, Long]) + checkAll(s"$instance[Singletons]", tests[Singletons].foldable[Int, Long]) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Foldable[Tree]])) - locally { + locally: import auto.foldable.given validate("auto.foldable") - } - locally { + locally: import semiInstances.given validate("semiauto.foldable") - } - locally { + locally: import derivedInstances.* val instance = "derived.foldable" checkAll(s"$instance[IList]", tests[IList].foldable[Int, Long]) @@ -65,8 +64,8 @@ class FoldableSuite extends KittensSuite: checkAll(s"$instance[Many]", tests[Many].foldable[Int, Long]) checkAll(s"$instance[AtMostOne]", tests[AtMostOne].foldable[Int, Long]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].foldable[Int, Long]) + checkAll(s"$instance[Singletons]", tests[Singletons].foldable[Int, Long]) checkAll(s"$instance is Serializable", SerializableTests.serializable(Foldable[Tree])) - } end FoldableSuite @@ -91,6 +90,7 @@ object FoldableSuite: given Foldable[Many] = semiauto.foldable given Foldable[AtMostOne] = semiauto.foldable given Foldable[AtLeastOne] = semiauto.foldable + given Foldable[Singletons] = semiauto.foldable object derivedInstances: case class IList[A](x: ADTs.IList[A]) derives Foldable @@ -102,6 +102,7 @@ object FoldableSuite: case class Many[+A](x: ADTs.Many[A]) derives Foldable case class AtMostOne[+A](x: ADTs.AtMostOne[A]) derives Foldable case class AtLeastOne[+A](x: ADTs.AtLeastOne[A]) derives Foldable + case class Singletons[A](x: ADTs.Singletons[A]) derives Foldable final case class Nel[+A](head: A, tail: List[A]) object Nel: diff --git a/core/src/test/scala-3/cats/derived/FunctorSuite.scala b/core/src/test/scala-3/cats/derived/FunctorSuite.scala index b13f7159..f588446e 100644 --- a/core/src/test/scala-3/cats/derived/FunctorSuite.scala +++ b/core/src/test/scala-3/cats/derived/FunctorSuite.scala @@ -44,19 +44,18 @@ class FunctorSuite extends KittensSuite: checkAll(s"$instance[Many]", tests[Many].functor[Boolean, Int, Boolean]) checkAll(s"$instance[AtMostOne]", tests[AtMostOne].functor[Boolean, Int, Boolean]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].functor[Boolean, Int, Boolean]) + checkAll(s"$instance[Singletons]", tests[Singletons].functor[Boolean, Int, Boolean]) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Functor[Tree]])) - locally { + locally: import auto.functor.given validate("auto.functor") - } - locally { + locally: import semiInstances.given validate("semiauto.functor") - } - locally { + locally: import derivedInstances.* val instance = "derived.functor" checkAll(s"$instance[IList]", tests[IList].functor[Int, String, Long]) @@ -68,8 +67,8 @@ class FunctorSuite extends KittensSuite: checkAll(s"$instance[Many]", tests[Many].functor[Boolean, Int, Boolean]) checkAll(s"$instance[AtMostOne]", tests[AtMostOne].functor[Boolean, Int, Boolean]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].functor[Boolean, Int, Boolean]) + checkAll(s"$instance[Singletons]", tests[Singletons].functor[Boolean, Int, Boolean]) checkAll(s"$instance is Serializable", SerializableTests.serializable(Functor[Tree])) - } end FunctorSuite @@ -95,6 +94,7 @@ object FunctorSuite: given Functor[Many] = semiauto.functor given Functor[AtMostOne] = semiauto.functor given Functor[AtLeastOne] = semiauto.functor + given Functor[Singletons] = semiauto.functor object derivedInstances: case class IList[A](x: ADTs.IList[A]) derives Functor @@ -106,5 +106,6 @@ object FunctorSuite: case class Many[+A](x: ADTs.Many[A]) derives Functor case class AtMostOne[+A](x: ADTs.AtMostOne[A]) derives Functor case class AtLeastOne[+A](x: ADTs.AtLeastOne[A]) derives Functor + case class Singletons[A](x: ADTs.Singletons[A]) derives Functor end FunctorSuite diff --git a/core/src/test/scala-3/cats/derived/HashSuite.scala b/core/src/test/scala-3/cats/derived/HashSuite.scala index 87a88f76..e54a1c17 100644 --- a/core/src/test/scala-3/cats/derived/HashSuite.scala +++ b/core/src/test/scala-3/cats/derived/HashSuite.scala @@ -3,7 +3,6 @@ package cats.derived import cats.Hash import cats.kernel.laws.discipline.* import scala.compiletime.* -import scala.util.hashing.MurmurHash3 class HashSuite extends KittensSuite: import HashSuite.* @@ -16,36 +15,33 @@ class HashSuite extends KittensSuite: checkAll(s"$instance[IList[Int]]", tests[IList[Int]].hash) checkAll(s"$instance[Inner]", tests[Inner].hash) checkAll(s"$instance[Outer]", tests[Outer].hash) - // FIXME: typelevel/cats#2878 - // checkAll(s"$instance[Interleaved[Int]]", tests[Interleaved[Int]].hash) + checkAll(s"$instance[Interleaved[Int]]", tests[Interleaved[Int]].hash) checkAll(s"$instance[Tree[Int]]", tests[Tree[Int]].hash) checkAll(s"$instance[Recursive]", tests[Recursive].hash) checkAll(s"$instance[EnumK0]", tests[EnumK0].hash) + checkAll(s"$instance[Singletons[Int]]", tests[Singletons[Int]].hash) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Hash[Inner]])) - locally { + locally: import auto.hash.given validate("auto.hash") - } - locally { + locally: import semiInstances.given validate("semiauto.hash") - } - locally { + locally: import derivedInstances.* val instance = "derived.hash" checkAll(s"$instance[IList[Int]]", tests[IList[Int]].hash) checkAll(s"$instance[Inner]", tests[Inner].hash) checkAll(s"$instance[Outer]", tests[Outer].hash) - // FIXME: typelevel/cats#2878 - // checkAll(s"$context[Interleaved[Int]]", tests[Interleaved[Int]].hash) + checkAll(s"$instance[Interleaved[Int]]", tests[Interleaved[Int]].hash) checkAll(s"$instance[Tree[Int]]", tests[Tree[Int]].hash) checkAll(s"$instance[Recursive]", tests[Recursive].hash) checkAll(s"$instance[EnumK0]", tests[EnumK0].hash) + checkAll(s"$instance[Singletons[Int]]", tests[Singletons[Int]].hash) checkAll(s"$instance is Serializable", SerializableTests.serializable(Hash[Inner])) - } end HashSuite @@ -60,6 +56,7 @@ object HashSuite: given Hash[Tree[Int]] = semiauto.hash given Hash[Recursive] = semiauto.hash given Hash[EnumK0] = semiauto.hash + given Hash[Singletons[Int]] = semiauto.hash object derivedInstances: case class IList[A](x: ADTs.IList[A]) derives Hash @@ -69,5 +66,6 @@ object HashSuite: case class Tree[A](x: ADTs.Tree[A]) derives Hash case class Recursive(x: ADTs.Recursive) derives Hash case class EnumK0(x: ADTs.EnumK0) derives Hash + case class Singletons[A](x: ADTs.Singletons[A]) derives Hash end HashSuite diff --git a/core/src/test/scala-3/cats/derived/InvariantSuite.scala b/core/src/test/scala-3/cats/derived/InvariantSuite.scala index c89d202d..10f7bb9d 100644 --- a/core/src/test/scala-3/cats/derived/InvariantSuite.scala +++ b/core/src/test/scala-3/cats/derived/InvariantSuite.scala @@ -42,19 +42,18 @@ class InvariantSuite extends KittensSuite: checkAll(s"$instance[Many]", tests[Many].invariant[MiniInt, String, Boolean]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].invariant[MiniInt, String, Boolean]) checkAll(s"$instance[AtMostOne]", tests[AtMostOne].invariant[MiniInt, String, Boolean]) + checkAll(s"$instance[Singletons]", tests[Singletons].invariant[MiniInt, String, Boolean]) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Invariant[TreeF]])) - locally { + locally: import auto.invariant.given validate("auto.invariant") - } - locally { + locally: import semiInstances.given validate("semiauto.invariant") - } - locally { + locally: import derivedInstances.* val instance = "derived.invariant" checkAll(s"$instance[IList]", tests[IList].invariant[MiniInt, String, Boolean]) @@ -63,8 +62,8 @@ class InvariantSuite extends KittensSuite: checkAll(s"$instance[Many]", tests[Many].invariant[MiniInt, String, Boolean]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].invariant[MiniInt, String, Boolean]) checkAll(s"$instance[AtMostOne]", tests[AtMostOne].invariant[MiniInt, String, Boolean]) + checkAll(s"$instance[Singletons]", tests[Singletons].invariant[MiniInt, String, Boolean]) checkAll(s"$instance is Serializable", SerializableTests.serializable(Invariant[AtMostOne])) - } end InvariantSuite @@ -93,6 +92,7 @@ object InvariantSuite: given Invariant[Many] = semiauto.invariant given Invariant[AtMostOne] = semiauto.invariant given Invariant[AtLeastOne] = semiauto.invariant + given Invariant[Singletons] = semiauto.invariant object derivedInstances: case class Bivariant[A](x: ADTs.Bivariant[A]) derives Invariant @@ -101,5 +101,6 @@ object InvariantSuite: case class Many[A](x: ADTs.Many[A]) derives Invariant case class AtMostOne[A](x: ADTs.AtMostOne[A]) derives Invariant case class AtLeastOne[A](x: ADTs.AtLeastOne[A]) derives Invariant + case class Singletons[A](x: ADTs.Singletons[A]) derives Invariant end InvariantSuite diff --git a/core/src/test/scala-3/cats/derived/KittensSuite.scala b/core/src/test/scala-3/cats/derived/KittensSuite.scala index 817c8524..47bf5511 100644 --- a/core/src/test/scala-3/cats/derived/KittensSuite.scala +++ b/core/src/test/scala-3/cats/derived/KittensSuite.scala @@ -20,7 +20,7 @@ import cats.Eq import cats.platform.Platform import cats.syntax.AllSyntax import munit.DisciplineSuite -import org.scalacheck.{Arbitrary, Cogen} +import org.scalacheck.{Arbitrary, Cogen, Gen} import org.scalacheck.Test.Parameters import scala.deriving.Mirror @@ -30,6 +30,7 @@ import scala.quoted.* * corresponding CatsSuite in the Cat project, this trait does not mix in any instances. */ abstract class KittensSuite extends KittensSuite.WithoutEq, ADTs.EqInstances: + given [A <: Singleton: ValueOf]: Eq[A] = Eq.allEqual given [A <: Product](using mirror: Mirror.ProductOf[A], via: Eq[mirror.MirroredElemTypes]): Eq[A] = Eq.by(Tuple.fromProductTyped) @@ -50,8 +51,9 @@ object KittensSuite: .withMaxSize(if Platform.isJvm then 10 else 5) .withMinSize(0) - given [A: Arbitrary]: Arbitrary[List[A]] = - Arbitrary.arbContainer + given [A: Arbitrary]: Arbitrary[List[A]] = Arbitrary.arbContainer + given [A <: Singleton: ValueOf]: Arbitrary[A] = Arbitrary(Gen.const(valueOf[A])) + given [A <: Singleton: ValueOf]: Cogen[A] = Cogen((seed, _) => seed) given [A <: Product](using mirror: Mirror.ProductOf[A], via: Arbitrary[mirror.MirroredElemTypes]): Arbitrary[A] = Arbitrary(via.arbitrary.map(mirror.fromTuple)) diff --git a/core/src/test/scala-3/cats/derived/NonEmptyTraverseSuite.scala b/core/src/test/scala-3/cats/derived/NonEmptyTraverseSuite.scala index 8c8097b2..194c270e 100644 --- a/core/src/test/scala-3/cats/derived/NonEmptyTraverseSuite.scala +++ b/core/src/test/scala-3/cats/derived/NonEmptyTraverseSuite.scala @@ -17,10 +17,8 @@ package cats.derived import cats.{Eq, NonEmptyTraverse} -import cats.data.{NonEmptyList, NonEmptyVector, OneAnd} +import cats.data.{NonEmptyList, OneAnd} import cats.laws.discipline.* -import cats.laws.discipline.arbitrary.* -import cats.syntax.all.given import scala.compiletime.* class NonEmptyTraverseSuite extends KittensSuite: @@ -63,22 +61,24 @@ class NonEmptyTraverseSuite extends KittensSuite: s"$instance[AtLeastOne]", tests[AtLeastOne].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option] ) + checkAll( + s"$instance[Singletons]", + tests[Singletons].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option] + ) checkAll( s"$instance is Serializable", SerializableTests.serializable(summonInline[NonEmptyTraverse[Tree]]) ) - locally { + locally: import auto.nonEmptyTraverse.given validate("auto.nonEmptyTraverse") - } - locally { + locally: import semiInstances.given validate("semiauto.nonEmptyTraverse") - } - locally { + locally: import derivedInstances.* val instance = "derived.nonEmptyTraverse" checkAll( @@ -101,8 +101,11 @@ class NonEmptyTraverseSuite extends KittensSuite: s"$instance[AtLeastOne]", tests[AtLeastOne].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option] ) + checkAll( + s"$instance[Singletons]", + tests[Singletons].nonEmptyTraverse[Option, Int, Int, Int, Int, Option, Option] + ) checkAll(s"$instance is Serializable", SerializableTests.serializable(NonEmptyTraverse[Tree])) - } end NonEmptyTraverseSuite @@ -122,6 +125,7 @@ object NonEmptyTraverseSuite: given NonEmptyTraverse[Interleaved] = semiauto.nonEmptyTraverse given NonEmptyTraverse[EnumK1] = semiauto.nonEmptyTraverse given NonEmptyTraverse[AtLeastOne] = semiauto.nonEmptyTraverse + given NonEmptyTraverse[Singletons] = semiauto.nonEmptyTraverse object derivedInstances: case class ICons[A](x: ADTs.ICons[A]) derives NonEmptyTraverse @@ -129,5 +133,6 @@ object NonEmptyTraverseSuite: case class Interleaved[A](x: ADTs.Interleaved[A]) derives NonEmptyTraverse case class EnumK1[A](x: ADTs.EnumK1[A]) derives NonEmptyTraverse case class AtLeastOne[A](x: ADTs.AtLeastOne[A]) derives NonEmptyTraverse + case class Singletons[A](x: ADTs.Singletons[A]) derives NonEmptyTraverse end NonEmptyTraverseSuite diff --git a/core/src/test/scala-3/cats/derived/OrderSuite.scala b/core/src/test/scala-3/cats/derived/OrderSuite.scala index 657bdeb8..0a26607c 100644 --- a/core/src/test/scala-3/cats/derived/OrderSuite.scala +++ b/core/src/test/scala-3/cats/derived/OrderSuite.scala @@ -34,19 +34,18 @@ class OrderSuite extends KittensSuite: checkAll(s"$instance[Recursive]", tests[Recursive].order) checkAll(s"$instance[GenericAdt[Int]]", tests[GenericAdt[Int]].order) checkAll(s"$instance[EnumK0]", tests[EnumK0].order) + checkAll(s"$instance[Singletons[Int]]", tests[Singletons[Int]].order) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Order[Interleaved[Int]]])) - locally { + locally: import auto.order.given validate("auto.order") - } - locally { + locally: import semiInstances.given validate("semiauto.order") - } - locally { + locally: import derivedInstances.* val instance = "derived.order" checkAll(s"$instance[Inner]", tests[Inner].order) @@ -55,8 +54,8 @@ class OrderSuite extends KittensSuite: checkAll(s"$instance[Recursive]", tests[Recursive].order) checkAll(s"$instance[GenericAdt[Int]]", tests[GenericAdt[Int]].order) checkAll(s"$instance[EnumK0]", tests[EnumK0].order) + checkAll(s"$instance[Singletons[Int]]", tests[Singletons[Int]].order) checkAll(s"$instance is Serializable", SerializableTests.serializable(Order[Interleaved[Int]])) - } end OrderSuite @@ -70,6 +69,7 @@ object OrderSuite: given Order[Recursive] = semiauto.order given Order[GenericAdt[Int]] = semiauto.order given Order[EnumK0] = semiauto.order + given Order[Singletons[Int]] = semiauto.order object derivedInstances: case class Inner(x: ADTs.Inner) derives Order @@ -78,5 +78,6 @@ object OrderSuite: case class Recursive(x: ADTs.Recursive) derives Order case class GenericAdt[A](x: ADTs.GenericAdt[A]) derives Order case class EnumK0(x: ADTs.EnumK0) derives Order + case class Singletons[A](x: ADTs.Singletons[A]) derives Order end OrderSuite diff --git a/core/src/test/scala-3/cats/derived/PartialOrderSuite.scala b/core/src/test/scala-3/cats/derived/PartialOrderSuite.scala index 53e89575..5e79575c 100644 --- a/core/src/test/scala-3/cats/derived/PartialOrderSuite.scala +++ b/core/src/test/scala-3/cats/derived/PartialOrderSuite.scala @@ -36,27 +36,25 @@ class PartialOrderSuite extends KittensSuite: checkAll(s"$instance[Recursive]", tests[Recursive].partialOrder) checkAll(s"$instance[Box[KeyValue]]", tests[Box[KeyValue]].partialOrder) checkAll(s"$instance[EnumK0]", tests[EnumK0].partialOrder) - checkAll(s"$instance is Serialiable", SerializableTests.serializable(summonInline[PartialOrder[Tree[Int]]])) - test(s"$instance respects existing instances") { + checkAll(s"$instance[Singletons[Int]]", tests[Singletons[Int]].partialOrder) + checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[PartialOrder[Tree[Int]]])) + test(s"$instance 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 { + locally: import auto.partialOrder.given validate("auto.partialOrder") - } - locally { + locally: import semiInstances.given validate("semiauto.partialOrder") - } - locally { + locally: import derivedInstances.* val instance = "derived.partialOrder" checkAll(s"$instance[IList[Int]]", tests[IList[Int]].partialOrder) @@ -67,8 +65,8 @@ class PartialOrderSuite extends KittensSuite: checkAll(s"$instance[Recursive]", tests[Recursive].partialOrder) checkAll(s"$instance[BoxKV]", tests[BoxKV].partialOrder) checkAll(s"$instance[EnumK0]", tests[EnumK0].partialOrder) + checkAll(s"$instance[Singletons[Int]]", tests[Singletons[Int]].partialOrder) checkAll(s"$instance is Serialiable", SerializableTests.serializable(PartialOrder[Tree[Int]])) - } end PartialOrderSuite @@ -84,6 +82,7 @@ object PartialOrderSuite: given PartialOrder[Recursive] = semiauto.partialOrder given PartialOrder[Box[KeyValue]] = semiauto.partialOrder given PartialOrder[EnumK0] = semiauto.partialOrder + given PartialOrder[Singletons[Int]] = semiauto.partialOrder object derivedInstances: case class IList[A](x: ADTs.IList[A]) derives PartialOrder @@ -93,6 +92,7 @@ object PartialOrderSuite: case class Outer(x: ADTs.Outer) derives PartialOrder case class Recursive(x: ADTs.Recursive) derives PartialOrder case class EnumK0(x: ADTs.EnumK0) derives PartialOrder + case class Singletons[A](x: ADTs.Singletons[A]) derives PartialOrder case class BoxKV(x: Box[KeyValue]) derives PartialOrder final case class KeyValue(key: String, value: Int) diff --git a/core/src/test/scala-3/cats/derived/PureSuite.scala b/core/src/test/scala-3/cats/derived/PureSuite.scala index 3e083597..19800820 100644 --- a/core/src/test/scala-3/cats/derived/PureSuite.scala +++ b/core/src/test/scala-3/cats/derived/PureSuite.scala @@ -35,34 +35,28 @@ class PureSuite extends KittensSuite: test(s"$instance[CaseClassWOption]")(assert(3.14.pure[CaseClassWOption] == CaseClassWOption(Some(3.14)))) test(s"$instance[NelOption]")(assert(42.pure[NelOption] == NonEmptyList.of(Some(42)))) test(s"$instance[Interleaved]")(assert('x'.pure[Interleaved] == Interleaved(0, 'x', 0, Vector('x'), ""))) + test(s"$instance[Singletons]")(assert('x'.pure[Singletons] == Singletons('x'))) test(s"$instance respects existing instances")(assert(().pure[BoxColor] == Box(Color(255, 255, 255)))) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Pure[Interleaved]])) - locally { + locally: import auto.pure.given validate("auto.pure") testNoInstance("Pure", "IList") testNoInstance("Pure", "Snoc") - } - locally { + locally: import semiInstances.given validate("semiauto.pure") testNoInstance("Pure", "IList") testNoInstance("Pure", "Snoc") - } - locally { + locally: import derivedInstances.* val instance = "derived.pure" checkAll(s"$instance is Serializable", SerializableTests.serializable(Pure[Interleaved])) - test(s"$instance[CaseClassWOption]")( - assert(3.14.pure[CaseClassWOption].x == ADTs.CaseClassWOption(Some(3.14))) - ) - test(s"$instance[Interleaved]")( - assert('x'.pure[Interleaved].x == ADTs.Interleaved(0, 'x', 0, Vector('x'), "")) - ) - } + test(s"$instance[CaseClassWOption]")(assert(3.14.pure[CaseClassWOption].x == ADTs.CaseClassWOption(Some(3.14)))) + test(s"$instance[Interleaved]")(assert('x'.pure[Interleaved].x == ADTs.Interleaved(0, 'x', 0, Vector('x'), ""))) end PureSuite @@ -80,6 +74,7 @@ object PureSuite: given Pure[CaseClassWOption] = semiauto.pure given Pure[NelOption] = semiauto.pure given Pure[Interleaved] = semiauto.pure + given Pure[Singletons] = semiauto.pure given Pure[BoxColor] = semiauto.pure object derivedInstances: diff --git a/core/src/test/scala-3/cats/derived/ReducibleSuite.scala b/core/src/test/scala-3/cats/derived/ReducibleSuite.scala index c30ab3f0..ea79ecb7 100644 --- a/core/src/test/scala-3/cats/derived/ReducibleSuite.scala +++ b/core/src/test/scala-3/cats/derived/ReducibleSuite.scala @@ -19,7 +19,6 @@ package cats.derived import cats.{Eval, Reducible} import cats.data.{NonEmptyList, OneAnd} import cats.laws.discipline.* -import cats.laws.discipline.arbitrary.* import cats.syntax.all.given import scala.compiletime.* @@ -40,19 +39,18 @@ class ReducibleSuite extends KittensSuite: checkAll(s"$instance[BoxZipper]", tests[BoxZipper].reducible[Option, Int, Long]) checkAll(s"$instance[EnumK1]", tests[EnumK1].reducible[Option, Int, Long]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].reducible[Option, Int, Long]) + checkAll(s"$instance[Singletons]", tests[Singletons].reducible[Option, Int, Long]) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Reducible[Tree]])) - locally { + locally: import auto.reducible.given validate("auto.reducible") - } - locally { + locally: import semiInstances.given validate("semiauto.reducible") - } - locally { + locally: import derivedInstances.* val instance = "derived.reducible" checkAll(s"$instance[ICons]", tests[ICons].reducible[Option, Int, Long]) @@ -60,8 +58,8 @@ class ReducibleSuite extends KittensSuite: checkAll(s"$instance[Interleaved]", tests[Interleaved].reducible[Option, Int, Long]) checkAll(s"$instance[EnumK1]", tests[EnumK1].reducible[Option, Int, Long]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].reducible[Option, Int, Long]) + checkAll(s"$instance[Singletons]", tests[Singletons].reducible[Option, Int, Long]) checkAll(s"$instance is Serializable", SerializableTests.serializable(Reducible[Tree])) - } end ReducibleSuite @@ -83,6 +81,7 @@ object ReducibleSuite: given Reducible[BoxZipper] = semiauto.reducible given Reducible[EnumK1] = semiauto.reducible given Reducible[AtLeastOne] = semiauto.reducible + given Reducible[Singletons] = semiauto.reducible object derivedInstances: case class ICons[A](x: ADTs.ICons[A]) derives Reducible @@ -90,6 +89,7 @@ object ReducibleSuite: case class Interleaved[A](x: ADTs.Interleaved[A]) derives Reducible case class EnumK1[A](x: ADTs.EnumK1[A]) derives Reducible case class AtLeastOne[A](x: ADTs.AtLeastOne[A]) derives Reducible + case class Singletons[A](x: ADTs.Singletons[A]) derives Reducible final case class Zipper[+A](left: List[A], focus: A, right: List[A]) object Zipper: diff --git a/core/src/test/scala-3/cats/derived/ShowPrettySuite.scala b/core/src/test/scala-3/cats/derived/ShowPrettySuite.scala index 69c319e7..ced9f73c 100644 --- a/core/src/test/scala-3/cats/derived/ShowPrettySuite.scala +++ b/core/src/test/scala-3/cats/derived/ShowPrettySuite.scala @@ -15,7 +15,7 @@ class ShowPrettySuite extends KittensSuite: inline def validate(instance: String): Unit = checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[ShowPretty[IntTree]])) - test(s"$instance[Foo]") { + test(s"$instance[Foo]"): val value = Foo(42, Option("Hello")) val pretty = """ |Foo( @@ -23,11 +23,9 @@ class ShowPrettySuite extends KittensSuite: | b = Some(Hello) |) """.stripMargin.trim - assertEquals(show(value), pretty) - } - test(s"$instance[Outer]") { + test(s"$instance[Outer]"): val value = Outer(Inner(3)) val pretty = """ |Outer( @@ -36,11 +34,9 @@ class ShowPrettySuite extends KittensSuite: | ) |) """.stripMargin.trim - assertEquals(show(value), pretty) - } - test(s"$instance[IntTree]") { + test(s"$instance[IntTree]"): val value: IntTree = IntNode(IntLeaf(1), IntNode(IntNode(IntLeaf(2), IntLeaf(3)), IntLeaf(4))) val pretty = """ |IntNode( @@ -62,22 +58,18 @@ class ShowPrettySuite extends KittensSuite: | ) |) """.stripMargin.trim - assertEquals(show(value), pretty) - } - test(s"$instance[GenericAdt[Int]]") { + test(s"$instance[GenericAdt[Int]]"): val value: GenericAdt[Int] = GenericAdtCase(Some(1)) val pretty = """ |GenericAdtCase( | value = Some(1) |) """.stripMargin.trim - assertEquals(show(value), pretty) - } - test(s"$instance[People]") { + test(s"$instance[People]"): val value = People("Kai", ContactInfo("303-123-4567", Address("123 1st St", "New York", "NY"))) val pretty = """ |People( @@ -88,11 +80,9 @@ class ShowPrettySuite extends KittensSuite: | ) |) """.stripMargin.trim - assertEquals(show(value), pretty) - } - test(s"$instance[ListField]") { + test(s"$instance[ListField]"): val value = ListField("a", List(ListFieldChild(1))) val pretty = """ |ListField( @@ -102,11 +92,9 @@ class ShowPrettySuite extends KittensSuite: | )) |) """.stripMargin.trim - assertEquals(show(value), pretty) - } - test(s"$instance[Interleaved[Int]]") { + test(s"$instance[Interleaved[Int]]"): val value = Interleaved(1, 2, 3, Vector(4, 5, 6), "789") val pretty = """ |Interleaved( @@ -117,11 +105,9 @@ class ShowPrettySuite extends KittensSuite: | s = 789 |) """.stripMargin.trim - assertEquals(show(value), pretty) - } - test(s"$instance[Tree[Int]]") { + test(s"$instance[Tree[Int]]"): val value: Tree[Int] = Node(Leaf(1), Node(Node(Leaf(2), Leaf(3)), Leaf(4))) val pretty = """ |Node( @@ -143,32 +129,38 @@ class ShowPrettySuite extends KittensSuite: | ) |) """.stripMargin.trim + assertEquals(show(value), pretty) + test(s"$instance[Singletons[Int]]"): + val value = Singletons(313) + val pretty = """ + |Singletons( + | value = 313, + | str = Scala, + | lng = 42, + | dbl = 3.14 + |) + """.stripMargin.trim assertEquals(show(value), pretty) - } - test(s"$instance respects existing instances") { + test(s"$instance respects existing instances"): val value = Box(Bogus(42)) val pretty = """ |Box( | content = Blah |) """.stripMargin.trim - assertEquals(show(value), pretty) - } end validate - locally { + locally: import auto.showPretty.given validate("auto.showPretty") - } - locally { + locally: import semiInstances.given validate("semiauto.showPretty") - } end ShowPrettySuite @@ -192,6 +184,7 @@ object ShowPrettySuite: given ShowPretty[ListField] = semiauto.showPretty given ShowPretty[Interleaved[Int]] = semiauto.showPretty given ShowPretty[Tree[Int]] = semiauto.showPretty + given ShowPretty[Singletons[Int]] = semiauto.showPretty given ShowPretty[Box[Bogus]] = semiauto.showPretty object derivedInstances: @@ -204,6 +197,7 @@ object ShowPrettySuite: case class GenericAdt[A](x: ADTs.GenericAdt[A]) derives ShowPretty case class Interleaved[A](x: ADTs.Interleaved[A]) derives ShowPretty case class Tree[A](x: ADTs.Tree[A]) derives ShowPretty + case class Singletons[A](x: ADTs.Singletons[A]) derives ShowPretty case class BoxBogus(x: Box[Bogus]) derives ShowPretty end ShowPrettySuite diff --git a/core/src/test/scala-3/cats/derived/ShowSuite.scala b/core/src/test/scala-3/cats/derived/ShowSuite.scala index b695fba3..9472b070 100644 --- a/core/src/test/scala-3/cats/derived/ShowSuite.scala +++ b/core/src/test/scala-3/cats/derived/ShowSuite.scala @@ -15,81 +15,73 @@ class ShowSuite extends KittensSuite: inline def validate(instance: String): Unit = checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Show[Foo]])) - test(s"$instance[Foo]") { + test(s"$instance[Foo]"): val value = Foo(42, Option("Hello")) val shown = "Foo(i = 42, b = Some(Hello))" assertEquals(show(value), shown) - } - test(s"$instance[Outer]") { + test(s"$instance[Outer]"): val value = Outer(Inner(3)) val shown = "Outer(in = Inner(i = 3))" assertEquals(show(value), shown) - } - test(s"$instance[IntTree]") { + test(s"$instance[IntTree]"): val value: IntTree = IntNode(IntLeaf(1), IntNode(IntNode(IntLeaf(2), IntLeaf(3)), IntLeaf(4))) val shown = "IntNode(l = IntLeaf(t = 1), r = IntNode(l = IntNode(l = IntLeaf(t = 2), r = IntLeaf(t = 3)), r = IntLeaf(t = 4)))" assertEquals(show(value), shown) - } - test(s"$instance[GenericAdt[Int]]") { + test(s"$instance[GenericAdt[Int]]"): val value: GenericAdt[Int] = GenericAdtCase(Some(1)) val shown = "GenericAdtCase(value = Some(1))" assertEquals(show(value), shown) - } - test(s"$instance[People]") { + test(s"$instance[People]"): val value = People("Kai", ContactInfo("303-123-4567", Address("123 1st St", "New York", "NY"))) val shown = "People(name = Kai, contactInfo = ContactInfo(phoneNumber = 303-123-4567, address = 123 1st St New York NY))" assertEquals(show(value), shown) - } - test(s"$instance[ListField]") { + test(s"$instance[ListField]"): val value = ListField("a", List(ListFieldChild(1))) val shown = "ListField(a = a, b = List(ListFieldChild(c = 1)))" assertEquals(show(value), shown) - } - test(s"$instance[Interleaved[Int]]") { + test(s"$instance[Interleaved[Int]]"): val value = Interleaved(1, 2, 3, Vector(4, 5, 6), "789") val shown = "Interleaved(i = 1, t = 2, l = 3, tt = Vector(4, 5, 6), s = 789)" assertEquals(show(value), shown) - } - test(s"$instance[Tree[Int]]") { + test(s"$instance[Tree[Int]]"): val value: Tree[Int] = Node(Leaf(1), Node(Node(Leaf(2), Leaf(3)), Leaf(4))) val shown = "Node(left = Leaf(value = 1), right = Node(left = Node(left = Leaf(value = 2), right = Leaf(value = 3)), right = Leaf(value = 4)))" assertEquals(show(value), shown) - } - test(s"$instance[EnumK0]") { + test(s"$instance[Singletons[Int]]"): + val value = Singletons(313) + val shown = "Singletons(value = 313, str = Scala, lng = 42, dbl = 3.14)" + assertEquals(show(value), shown) + + test(s"$instance[EnumK0]"): val value: EnumK0 = EnumK0.LeafI(3) - val shown = - "LeafI(value = 3)" + val shown = "LeafI(value = 3)" assertEquals(show(value), shown) - } - test(s"$instance respects existing instances") { + test(s"$instance respects existing instances"): val value = Box(Bogus(42)) val shown = "Box(content = Blah)" assertEquals(show(value), shown) - } end validate - locally { + locally: import auto.show.given validate("auto.show") - } - locally { + locally: import semiInstances.given validate("semiauto.show") - } end ShowSuite @@ -113,6 +105,7 @@ object ShowSuite: given Show[ListField] = semiauto.show given Show[Interleaved[Int]] = semiauto.show given Show[Tree[Int]] = semiauto.show + given Show[Singletons[Int]] = semiauto.show given Show[Box[Bogus]] = semiauto.show given Show[EnumK0] = semiauto.show @@ -127,6 +120,7 @@ object ShowSuite: case class GenericAdt[A](x: ADTs.GenericAdt[A]) derives Show case class Interleaved[A](x: ADTs.Interleaved[A]) derives Show case class Tree[A](x: ADTs.Tree[A]) derives Show + case class Singletons[A](x: ADTs.Singletons[A]) derives Show case class BoxBogus(x: Box[Bogus]) derives Show end ShowSuite diff --git a/core/src/test/scala-3/cats/derived/TraverseSuite.scala b/core/src/test/scala-3/cats/derived/TraverseSuite.scala index 7b4c9f16..3bdfd307 100644 --- a/core/src/test/scala-3/cats/derived/TraverseSuite.scala +++ b/core/src/test/scala-3/cats/derived/TraverseSuite.scala @@ -23,19 +23,18 @@ class TraverseSuite extends KittensSuite: checkAll(s"$instance[Many]", tests[Many].traverse[Int, Double, String, Long, Option, Option]) checkAll(s"$instance[AtMostOne]", tests[AtMostOne].traverse[Int, Double, String, Long, Option, Option]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].traverse[Int, Double, String, Long, Option, Option]) + checkAll(s"$instance[Singletons]", tests[Singletons].traverse[Int, Double, String, Long, Option, Option]) checkAll(s"$instance is Serializable", SerializableTests.serializable(summonInline[Traverse[Tree]])) - locally { + locally: import auto.traverse.given validate("auto.traverse") - } - locally { + locally: import semiInstances.given validate("semiauto.traverse") - } - locally { + locally: import derivedInstances.* val instance = "derived.traverse" checkAll(s"$instance[IList]", tests[IList].traverse[Int, Double, String, Long, Option, Option]) @@ -46,8 +45,8 @@ class TraverseSuite extends KittensSuite: checkAll(s"$instance[Many]", tests[Many].traverse[Int, Double, String, Long, Option, Option]) checkAll(s"$instance[AtMostOne]", tests[AtMostOne].traverse[Int, Double, String, Long, Option, Option]) checkAll(s"$instance[AtLeastOne]", tests[AtLeastOne].traverse[Int, Double, String, Long, Option, Option]) + checkAll(s"$instance[Singletons]", tests[Singletons].traverse[Int, Double, String, Long, Option, Option]) checkAll(s"$instance is Serializable", SerializableTests.serializable(Traverse[Tree])) - } end TraverseSuite @@ -70,6 +69,7 @@ object TraverseSuite: given Traverse[Many] = semiauto.traverse given Traverse[AtLeastOne] = semiauto.traverse given Traverse[AtMostOne] = semiauto.traverse + given Traverse[Singletons] = semiauto.traverse object derivedInstances: case class IList[A](x: ADTs.IList[A]) derives Traverse @@ -80,5 +80,6 @@ object TraverseSuite: case class Many[A](x: ADTs.Many[A]) derives Traverse case class AtMostOne[A](x: ADTs.AtMostOne[A]) derives Traverse case class AtLeastOne[A](x: ADTs.AtLeastOne[A]) derives Traverse + case class Singletons[A](x: ADTs.Singletons[A]) derives Traverse end TraverseSuite