Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Representable instance for Tuple2K #3832

Merged
merged 3 commits into from
Mar 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions core/src/main/scala/cats/data/Tuple2K.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,28 @@ sealed abstract private[data] class Tuple2KInstances1 extends Tuple2KInstances2
def F: Foldable[F] = FF
def G: Foldable[G] = GF
}

implicit def catsDataRepresentableForTuple2K[F[_], G[_]](implicit
FF: Representable[F],
GG: Representable[G]
): Representable.Aux[Tuple2K[F, G, *], Either[FF.Representation, GG.Representation]] =
new Representable[Tuple2K[F, G, *]] {
type Representation = Either[FF.Representation, GG.Representation]

val F = new Tuple2KFunctor[F, G] {
val F = FF.F
val G = GG.F
}

def index[A](f: Tuple2K[F, G, A]): Representation => A = {
case Left(i) => FF.index(f.first)(i)
case Right(i) => GG.index(f.second)(i)
}

def tabulate[A](f: Representation => A): Tuple2K[F, G, A] =
Tuple2K(FF.tabulate((x: FF.Representation) => f(Left(x))), GG.tabulate((x: GG.Representation) => f(Right(x))))
}

}

sealed abstract private[data] class Tuple2KInstances2 extends Tuple2KInstances3 {
Expand Down
31 changes: 31 additions & 0 deletions tests/src/test/scala/cats/tests/Tuple2KSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import cats.laws.discipline.arbitrary._
import cats.laws.discipline.eq._
import cats.laws.discipline.SemigroupalTests.Isomorphisms
import cats.syntax.eq._
import org.scalacheck.{Arbitrary, Cogen}
import org.scalacheck.Prop._

class Tuple2KSuite extends CatsSuite {
Expand Down Expand Up @@ -41,6 +42,36 @@ class Tuple2KSuite extends CatsSuite {

checkAll("Show[Tuple2K[Option, Option, Int]]", SerializableTests.serializable(Show[Tuple2K[Option, Option, Int]]))

{
type Pair[A] = (A, A)

//Scala 2.12 implicit resolution absolutely loses its mind here
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do these need to be implicit if you are passing them explicitly? Can we just make them normal vals?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good call! 👍

implicit val help_scala2_12: Representable.Aux[Tuple2K[Pair, Pair, *], Either[Boolean, Boolean]] =
Tuple2K.catsDataRepresentableForTuple2K[Pair, Pair]

val a: Arbitrary[Int] = implicitly[Arbitrary[Int]]
val b: Arbitrary[Tuple2K[Pair, Pair, Int]] = implicitly[Arbitrary[Tuple2K[Pair, Pair, Int]]]
val c: Arbitrary[Either[Boolean, Boolean]] = implicitly[Arbitrary[Either[Boolean, Boolean]]]
val d: Arbitrary[(Either[Boolean, Boolean]) => Int] = implicitly[Arbitrary[(Either[Boolean, Boolean]) => Int]]
val e: Eq[Tuple2K[Pair, Pair, Int]] = Eq[Tuple2K[Pair, Pair, Int]]
val f: Eq[Int] = Eq[Int]

checkAll(
"Representable[Tuple2K[Pair, Pair, *]]",
RepresentableTests[Tuple2K[Pair, Pair, *], Either[Boolean, Boolean]].representable[Int](
a,
b,
c,
d,
e,
f
)
)
checkAll("Representable[Tuple2K[Pair, Pair, *]]",
SerializableTests.serializable(Representable[Tuple2K[Pair, Pair, *]])
)
}

{
implicit val monoidK: MonoidK[ListWrapper] = ListWrapper.monoidK
checkAll("Tuple2K[ListWrapper, ListWrapper, *]", MonoidKTests[Tuple2K[ListWrapper, ListWrapper, *]].monoidK[Int])
Expand Down