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

Improve test coverage IdT #1623

Merged
merged 2 commits into from
Jul 1, 2017
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
67 changes: 46 additions & 21 deletions core/src/main/scala/cats/data/IdT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,24 @@ object IdT extends IdTInstances {
private[data] sealed trait IdTFunctor[F[_]] extends Functor[IdT[F, ?]] {
implicit val F0: Functor[F]

def map[A, B](fa: IdT[F, A])(f: A => B): IdT[F, B] =
override def map[A, B](fa: IdT[F, A])(f: A => B): IdT[F, B] =
fa.map(f)
}

private[data] sealed trait IdTMonad[F[_]] extends Monad[IdT[F, ?]] {
implicit val F0: Monad[F]
private[data] sealed trait IdTApply[F[_]] extends Apply[IdT[F, ?]] with IdTFunctor[F] {
implicit val F0: Apply[F]

override def ap[A, B](ff: IdT[F, A => B])(fa: IdT[F, A]): IdT[F, B] = fa.ap(ff)
}

def pure[A](a: A): IdT[F, A] =
IdT.pure(a)
private[data] sealed trait IdTApplicative[F[_]] extends Applicative[IdT[F, ?]] with IdTApply[F] {
implicit val F0: Applicative[F]

def pure[A](a: A): IdT[F, A] = IdT.pure(a)
}

private[data] sealed trait IdTFlatMap[F[_]] extends FlatMap[IdT[F, ?]] with IdTApply[F] {
implicit val F0: FlatMap[F]

def flatMap[A, B](fa: IdT[F, A])(f: A => IdT[F, B]): IdT[F, B] =
fa.flatMap(f)
Expand All @@ -55,6 +64,10 @@ private[data] sealed trait IdTMonad[F[_]] extends Monad[IdT[F, ?]] {
IdT(F0.tailRecM(a)(f(_).value))
}

private[data] sealed trait IdTMonad[F[_]] extends Monad[IdT[F, ?]] with IdTApplicative[F] with IdTFlatMap[F] {
implicit val F0: Monad[F]
}

private[data] sealed trait IdTFoldable[F[_]] extends Foldable[IdT[F, ?]] {
implicit val F0: Foldable[F]

Expand All @@ -71,46 +84,58 @@ private[data] sealed trait IdTFoldable[F[_]] extends Foldable[IdT[F, ?]] {
F0.get(fa.value)(idx)
}

private[data] sealed trait IdTTraverse[F[_]] extends Traverse[IdT[F, ?]] with IdTFoldable[F] {
private[data] sealed trait IdTTraverse[F[_]] extends Traverse[IdT[F, ?]] with IdTFoldable[F] with IdTFunctor[F] {
implicit val F0: Traverse[F]

def traverse[G[_]: Applicative, A, B](fa: IdT[F, A])(f: A => G[B]): G[IdT[F, B]] =
fa.traverse(f)
}

private[data] sealed abstract class IdTInstances1 {
private[data] sealed abstract class IdTInstances4 {
implicit def catsDataFunctorForIdT[F[_]](implicit F: Functor[F]): Functor[IdT[F, ?]] =
new IdTFunctor[F] {
implicit val F0: Functor[F] = F
}
new IdTFunctor[F] { implicit val F0: Functor[F] = F }
}

private[data] sealed abstract class IdTInstances3 extends IdTInstances4 {
implicit def catsDataApplyForIdT[F[_]](implicit F: Apply[F]): Apply[IdT[F, ?]] =
new IdTApply[F] { implicit val F0: Apply[F] = F }
}

private[data] sealed abstract class IdTInstances2 extends IdTInstances3 {
implicit def catsDataApplicativeForIdT[F[_]](implicit F: Applicative[F]): Applicative[IdT[F, ?]] =
new IdTApplicative[F] { implicit val F0: Applicative[F] = F }
}

private[data] sealed abstract class IdTInstances1 extends IdTInstances2 {
implicit def catsDataFlatMapForIdT[F[_]](implicit F: FlatMap[F]): FlatMap[IdT[F, ?]] =
new IdTFlatMap[F] { implicit val F0: FlatMap[F] = F }
}

private[data] sealed abstract class IdTInstances0 extends IdTInstances1 {

implicit def catsDataMonadForIdT[F[_]](implicit F: Monad[F]): Monad[IdT[F, ?]] =
new IdTMonad[F] {
implicit val F0: Monad[F] = F
}
new IdTMonad[F] { implicit val F0: Monad[F] = F }

implicit def catsDataFoldableForIdT[F[_]](implicit F: Foldable[F]): Foldable[IdT[F, ?]] =
new IdTFoldable[F] {
implicit val F0: Foldable[F] = F
}
new IdTFoldable[F] { implicit val F0: Foldable[F] = F }

implicit def catsDataOrderForIdT[F[_], A](implicit F: Order[F[A]]): Order[IdT[F, A]] =
implicit def catsDataEqForIdT[F[_], A](implicit F: Eq[F[A]]): Eq[IdT[F, A]] =
F.on(_.value)
}

private[data] sealed abstract class IdTInstances extends IdTInstances0 {

implicit def catsDataTraverseForIdT[F[_]](implicit F: Traverse[F]): Traverse[IdT[F, ?]] =
new IdTTraverse[F] {
implicit val F0: Traverse[F] = F
}
new IdTTraverse[F] { implicit val F0: Traverse[F] = F }

implicit def catsDataEqForIdT[F[_], A](implicit F: Eq[F[A]]): Eq[IdT[F, A]] =
implicit def catsDataOrderForIdT[F[_], A](implicit F: Order[F[A]]): Order[IdT[F, A]] =
F.on(_.value)

implicit def catsDataShowForIdT[F[_], A](implicit F: Show[F[A]]): Show[IdT[F, A]] =
functor.Contravariant[Show].contramap(F)(_.value)

implicit def catsDataMonadTransForIdT: MonadTrans[IdT] =
new MonadTrans[IdT] {
def liftT[M[_]: Monad, A](ma: M[A]): IdT[M, A] = IdT(ma)
}
}
5 changes: 3 additions & 2 deletions free/src/test/scala/cats/free/FreeTTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ class FreeTTests extends CatsSuite {
{
import StateT._
checkAll("FreeT[State[Int, ?], State[Int, ?], Int]", MonadStateTests[FreeTState, Int].monadState[Int, Int, Int])
checkAll("MonadState[FreeT[State[Int, ?],State[Int, ?], ?], Int]", SerializableTests.serializable(MonadState[FreeTState, Int]))
checkAll("MonadState[FreeT[State[Int, ?], State[Int, ?], ?], Int]", SerializableTests.serializable(MonadState[FreeTState, Int]))
}

{
checkAll("MonadTrans[FreeT[Option, ?[_], ?]]", MonadTransTests[FreeT[Option, ?[_], ?]].monadTrans[Option, Int, Int])
checkAll("FreeT[Option, Option, Int]]", MonadTransTests[FreeT[Option, ?[_], ?]].monadTrans[Option, Int, Int])
checkAll("MonadTrans[FreeT[Option, ?[_], Int, ?]]", SerializableTests.serializable(MonadTrans[FreeT[Option, ?[_], ?]]))
}

test("FlatMap stack safety tested with 50k flatMaps") {
Expand Down
3 changes: 2 additions & 1 deletion tests/src/test/scala/cats/tests/EitherTTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ class EitherTTests extends CatsSuite {

checkAll("EitherT[ListWrapper, String, Int]", MonadErrorTests[EitherT[ListWrapper, String, ?], String].monadError[Int, Int, Int])
checkAll("MonadError[EitherT[List, ?, ?]]", SerializableTests.serializable(MonadError[EitherT[ListWrapper, String, ?], String]))
checkAll("MonadTrans[EitherT[?[_], String, ?]]", MonadTransTests[EitherT[?[_], String, ?]].monadTrans[ListWrapper, Int, Int])
checkAll("EitherT[ListWrapper, String, Int]]", MonadTransTests[EitherT[?[_], String, ?]].monadTrans[ListWrapper, Int, Int])
checkAll("MonadTrans[EitherT[?[_], String, ?]]", SerializableTests.serializable(MonadTrans[EitherT[?[_], String, ?]]))
}

{
Expand Down
86 changes: 74 additions & 12 deletions tests/src/test/scala/cats/tests/IdTTests.scala
Original file line number Diff line number Diff line change
@@ -1,24 +1,86 @@
package cats.tests
package cats
package tests

import cats.{Foldable, Functor, Monad, Traverse}
import cats.data.IdT
import cats.laws.discipline.{CartesianTests, FoldableTests, FunctorTests, MonadTests, SerializableTests, TraverseTests}
import cats.kernel.laws.OrderLaws
import cats.laws.discipline._
import cats.laws.discipline.arbitrary._

class IdTTests extends CatsSuite {

implicit val iso = CartesianTests.Isomorphisms.invariant[IdT[List, ?]]
implicit val iso = CartesianTests.Isomorphisms.invariant[IdT[ListWrapper, ?]](IdT.catsDataFunctorForIdT(ListWrapper.functor))

checkAll("IdT[Functor, Int]", FunctorTests[IdT[List, ?]].functor[Int, Int, Int])
checkAll("Functor[IdT[List, ?]]", SerializableTests.serializable(Functor[IdT[List, ?]]))
{
implicit val F = ListWrapper.eqv[Option[Int]]

checkAll("IdT[List, Int]", MonadTests[IdT[List, ?]].monad[Int, Int, Int])
checkAll("Monad[IdT[List, ?]]", SerializableTests.serializable(Monad[IdT[List, ?]]))
checkAll("IdT[ListWrapper, Int]", OrderLaws[IdT[ListWrapper, Int]].eqv)
checkAll("Eq[IdT[ListWrapper, Int]]", SerializableTests.serializable(Eq[IdT[ListWrapper, Int]]))
}

checkAll("IdT[Option, Int]", FoldableTests[IdT[Option, ?]].foldable[Int, Int])
checkAll("Foldable[IdT[Option, ?]]", SerializableTests.serializable(Foldable[IdT[Option, ?]]))
{
implicit val F = ListWrapper.order[Int]

checkAll("IdT[Option, Int]", TraverseTests[IdT[Option, ?]].traverse[Int, Int, Int, Int, Option, Option])
checkAll("Traverse[IdT[Option, ?]]", SerializableTests.serializable(Traverse[IdT[Option, ?]]))
checkAll("IdT[ListWrapper, Int]", OrderLaws[IdT[ListWrapper, Int]].order)
checkAll("Order[IdT[ListWrapper, Int]]", SerializableTests.serializable(Order[IdT[ListWrapper, Int]]))
}

{
implicit val F = ListWrapper.functor

checkAll("IdT[ListWrapper, Int]", FunctorTests[IdT[ListWrapper, ?]].functor[Int, Int, Int])
checkAll("Functor[IdT[ListWrapper, ?]]", SerializableTests.serializable(Functor[IdT[ListWrapper, ?]]))
}

{
implicit val F = ListWrapper.applyInstance

checkAll("IdT[ListWrapper, Int]", ApplyTests[IdT[ListWrapper, ?]].apply[Int, Int, Int])
checkAll("Apply[IdT[ListWrapper, ?]]", SerializableTests.serializable(Apply[IdT[ListWrapper, ?]]))
}

{
implicit val F = ListWrapper.applicative

checkAll("IdT[ListWrapper, Int]", ApplicativeTests[IdT[ListWrapper, ?]].applicative[Int, Int, Int])
checkAll("Applicative[IdT[ListWrapper, ?]]", SerializableTests.serializable(Applicative[IdT[ListWrapper, ?]]))
}

{
implicit val F = ListWrapper.flatMap

checkAll("IdT[ListWrapper, Int]", FlatMapTests[IdT[ListWrapper, ?]].flatMap[Int, Int, Int])
checkAll("FlatMap[IdT[ListWrapper, ?]]", SerializableTests.serializable(FlatMap[IdT[ListWrapper, ?]]))
}

{
implicit val F = ListWrapper.monad

checkAll("IdT[ListWrapper, Int]", MonadTests[IdT[ListWrapper, ?]].monad[Int, Int, Int])
checkAll("Monad[IdT[ListWrapper, ?]]", SerializableTests.serializable(Monad[IdT[ListWrapper, ?]]))

checkAll("IdT[ListWrapper, Int]", MonadTransTests[IdT].monadTrans[ListWrapper, Int, Int])
checkAll("MonadTrans[IdT]", SerializableTests.serializable(MonadTrans[IdT]))
}

{
implicit val F = ListWrapper.foldable

checkAll("IdT[ListWrapper, Int]", FoldableTests[IdT[ListWrapper, ?]].foldable[Int, Int])
checkAll("Foldable[IdT[ListWrapper, ?]]", SerializableTests.serializable(Foldable[IdT[ListWrapper, ?]]))
}

{
implicit val F = ListWrapper.traverse

checkAll("IdT[ListWrapper, Int] with Option", TraverseTests[IdT[ListWrapper, ?]].traverse[Int, Int, Int, Int, Option, Option])
checkAll("Traverse[IdT[ListWrapper, ?]]", SerializableTests.serializable(Traverse[IdT[ListWrapper, ?]]))
}


test("flatMap and flatMapF consistent") {
forAll { (idT: IdT[Option, Int], f: Int => IdT[Option, Int]) =>
idT.flatMap(f) should === (idT.flatMapF(f(_).value))
}
}

}
4 changes: 3 additions & 1 deletion tests/src/test/scala/cats/tests/OptionTTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ class OptionTTests extends CatsSuite {

checkAll("OptionT[ListWrapper, Int]", MonoidKTests[OptionT[ListWrapper, ?]].monoidK[Int])
checkAll("MonoidK[OptionT[ListWrapper, ?]]", SerializableTests.serializable(MonoidK[OptionT[ListWrapper, ?]]))
checkAll("MonadTrans[OptionT]", MonadTransTests[OptionT].monadTrans[ListWrapper, Int, Int])

checkAll("OptionT[ListWrapper, Int]]", MonadTransTests[OptionT].monadTrans[ListWrapper, Int, Int])
checkAll("MonadTrans[OptionT]", SerializableTests.serializable(MonadTrans[OptionT]))

FlatMap[OptionT[ListWrapper, ?]]
Applicative[OptionT[ListWrapper, ?]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ class ReaderWriterStateTTests extends CatsSuite {
{
implicit val F: Monad[ListWrapper] = ListWrapper.monad

checkAll("ReaderWriterStateT[?[_], String, Int, String, ?]",
checkAll("ReaderWriterStateT[ListWrapper, String, Int, String, Int]]",
MonadTransTests[ReaderWriterStateT[?[_], String, Int, String, ?]].monadTrans[ListWrapper, Int, Int])
checkAll("MonadTrans[ReaderWriterStateT[?[_], String, Int, String, ?]]",
SerializableTests.serializable(MonadTrans[ReaderWriterStateT[?[_], String, Int, String, ?]]))
Expand Down
3 changes: 2 additions & 1 deletion tests/src/test/scala/cats/tests/WriterTTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ class WriterTTests extends CatsSuite {
checkAll("WriterT[ListWrapper, ListWrapper[Int], ?]", MonadWriterTests[WriterT[ListWrapper, ListWrapper[Int], ?], ListWrapper[Int]].monadWriter[Int, Int, Int])
checkAll("MonadWriter[WriterT[ListWrapper, ListWrapper[Int], ?], List[String]]", SerializableTests.serializable(MonadWriter[WriterT[ListWrapper, ListWrapper[Int], ?], ListWrapper[Int]]))

checkAll("MonadTrans[WriterT[?[_], ListWrapper[Int], ?]]", MonadTransTests[WriterT[?[_], ListWrapper[Int], ?]].monadTrans[ListWrapper, Int, Int])
checkAll("WriterT[ListWrapper, ListWrapper[Int], ?]]", MonadTransTests[WriterT[?[_], ListWrapper[Int], ?]].monadTrans[ListWrapper, Int, Int])
checkAll("MonadTrans[WriterT[?[_], ListWrapper[Int], ?]]", SerializableTests.serializable(MonadTrans[WriterT[?[_], ListWrapper[Int], ?]]))

Functor[WriterT[Id, ListWrapper[Int], ?]]
Apply[WriterT[Id, ListWrapper[Int], ?]]
Expand Down