From 7842594e5628b2467417d0f7126a0e9fa86c4e5c Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Wed, 12 Oct 2016 13:10:01 +0200 Subject: [PATCH 1/4] Upgrades to latest version of cats --- build.sbt | 8 ++-- src/main/scala/github4s/Github.scala | 7 ++-- src/main/scala/github4s/Implicits.scala | 32 +++++++++++---- .../free/interpreters/Interpreters.scala | 39 +++++++++++-------- .../github4s/integration/GHAuthSpec.scala | 2 +- .../github4s/integration/GHReposSpec.scala | 4 +- .../github4s/integration/GHUsersSpec.scala | 2 +- 7 files changed, 61 insertions(+), 33 deletions(-) diff --git a/build.sbt b/build.sbt index 489b1db34..bd234ce8d 100644 --- a/build.sbt +++ b/build.sbt @@ -17,8 +17,8 @@ lazy val buildSettings = Seq( licenses := Seq("Apache License, Version 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")) ) -lazy val cats = "0.6.0" -lazy val circe = "0.5.0-M2" +lazy val cats = "0.7.2" +lazy val circe = "0.5.2" lazy val dependencies = libraryDependencies ++= Seq( "org.typelevel" %% "cats-free" % cats, @@ -26,9 +26,11 @@ lazy val dependencies = libraryDependencies ++= Seq( "io.circe" %% "circe-core" % circe, "io.circe" %% "circe-generic" % circe, "io.circe" %% "circe-parser" % circe, + "com.github.mpilquist" %% "simulacrum" % "0.8.0", "org.scalatest" %% "scalatest" % "2.2.6" % "test", "com.ironcorelabs" %% "cats-scalatest" % "1.1.2" % "test", - "org.mock-server" % "mockserver-netty" % "3.10.4" % "test" + "org.mock-server" % "mockserver-netty" % "3.10.4" % "test", + compilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full) ) lazy val scalariformSettings = SbtScalariform.scalariformSettings ++ Seq( diff --git a/src/main/scala/github4s/Github.scala b/src/main/scala/github4s/Github.scala index 93a03dbfd..549488a98 100644 --- a/src/main/scala/github4s/Github.scala +++ b/src/main/scala/github4s/Github.scala @@ -1,7 +1,8 @@ package github4s import cats.data.{ OptionT, XorT } -import cats.{ MonadError, ~> } +import cats.{ MonadError, ~>, RecursiveTailRecM } +import cats.implicits._ import github4s.GithubResponses._ import github4s.app._ @@ -24,9 +25,9 @@ object Github { implicit class GithubIOSyntaxXOR[A](gio: GHIO[GHResponse[A]]) { - def exec[M[_]](implicit I: (GitHub4s ~> M), A: MonadError[M, Throwable]): M[GHResponse[A]] = gio foldMap I + def exec[M[_]](implicit I: (GitHub4s ~> M), A: MonadError[M, Throwable], TR: RecursiveTailRecM[M]): M[GHResponse[A]] = gio foldMap I def liftGH: XorT[GHIO, GHException, GHResult[A]] = XorT[GHIO, GHException, GHResult[A]](gio) } -} \ No newline at end of file +} diff --git a/src/main/scala/github4s/Implicits.scala b/src/main/scala/github4s/Implicits.scala index 849a3e3e8..83287394a 100644 --- a/src/main/scala/github4s/Implicits.scala +++ b/src/main/scala/github4s/Implicits.scala @@ -1,16 +1,30 @@ package github4s -import cats.std.FutureInstances -import cats.std.future._ -import cats.{ Monad, Id, Eval, MonadError } -import github4s.free.interpreters.Interpreters +import cats.implicits._ +import cats.{ Monad, Id, Eval, MonadError, FlatMap } +import github4s.free.interpreters._ import scala.concurrent.{ ExecutionContext, Future } -object implicits extends Interpreters with EvalInstances with IdInstances with FutureInstances +object implicits extends ProdInterpreters +object testimplicits extends TestInterpreters + +trait ProdInterpreters extends Interpreters[Eval] with EvalInstances { + + implicit val evalCaptureInstance = new Capture[Eval] { + override def capture[A](a: ⇒ A): Eval[A] = Eval.later(a) + } +} + +trait TestInterpreters extends Interpreters[Id] with IdInstances { + + implicit val idCaptureInstance = new Capture[Id] { + override def capture[A](a: ⇒ A): Id[A] = idMonad.pure(a) + } +} trait EvalInstances { - implicit val evalMonadError: MonadError[Eval, Throwable] = new MonadError[Eval, Throwable] { + implicit def evalMonadError(implicit FM: FlatMap[Eval]): MonadError[Eval, Throwable] = new MonadError[Eval, Throwable] { override def pure[A](x: A): Eval[A] = Eval.now(x) @@ -19,6 +33,8 @@ trait EvalInstances { override def flatMap[A, B](fa: Eval[A])(ff: A ⇒ Eval[B]): Eval[B] = fa.flatMap(ff) + override def tailRecM[A, B](a: A)(f: A ⇒ Eval[Either[A, B]]): Eval[B] = FM.tailRecM(a)(f) + override def raiseError[A](e: Throwable): Eval[A] = Eval.later({ throw e }) @@ -36,7 +52,7 @@ trait EvalInstances { trait IdInstances { - implicit def idMonadError(implicit I: Monad[Id]): MonadError[Id, Throwable] = new MonadError[Id, Throwable] { + implicit def idMonad(implicit I: Monad[Id], FM: FlatMap[Id]): MonadError[Id, Throwable] = new MonadError[Id, Throwable] { override def pure[A](x: A): Id[A] = I.pure(x) @@ -46,6 +62,8 @@ trait IdInstances { override def flatMap[A, B](fa: Id[A])(f: A ⇒ Id[B]): Id[B] = I.flatMap(fa)(f) + override def tailRecM[A, B](a: A)(f: A ⇒ Id[Either[A, B]]): Id[B] = FM.tailRecM(a)(f) + override def raiseError[A](e: Throwable): Id[A] = throw e override def handleErrorWith[A](fa: Id[A])(f: Throwable ⇒ Id[A]): Id[A] = { diff --git a/src/main/scala/github4s/free/interpreters/Interpreters.scala b/src/main/scala/github4s/free/interpreters/Interpreters.scala index b074d1cd4..8c100aba1 100644 --- a/src/main/scala/github4s/free/interpreters/Interpreters.scala +++ b/src/main/scala/github4s/free/interpreters/Interpreters.scala @@ -1,5 +1,6 @@ package github4s.free.interpreters +import cats.implicits._ import cats.{ MonadError, ApplicativeError, ~>, Eval } import github4s.GithubDefaultUrls._ import github4s.api.{ Users, Auth, Repos } @@ -7,11 +8,18 @@ import github4s.app.{ COGH01, GitHub4s } import github4s.free.algebra._ import io.circe.Decoder -trait Interpreters { +import simulacrum.typeclass - implicit def interpreters[M[_]]( +@typeclass trait Capture[M[_]] { + def capture[A](a: ⇒ A): M[A] +} + +trait Interpreters[M[_]] { + + implicit def interpreters( implicit - A: MonadError[M, Throwable] + A: MonadError[M, Throwable], + C: Capture[M] ): GitHub4s ~> M = { val c01interpreter: COGH01 ~> M = repositoryOpsInterpreter[M] or userOpsInterpreter[M] val all: GitHub4s ~> M = authOpsInterpreter[M] or c01interpreter @@ -21,44 +29,43 @@ trait Interpreters { /** * Lifts Repository Ops to an effect capturing Monad such as Task via natural transformations */ - def repositoryOpsInterpreter[M[_]](implicit A: ApplicativeError[M, Throwable]): RepositoryOp ~> M = new (RepositoryOp ~> M) { + def repositoryOpsInterpreter[M[_]](implicit A: ApplicativeError[M, Throwable], C: Capture[M]): RepositoryOp ~> M = new (RepositoryOp ~> M) { val repos = new Repos() def apply[A](fa: RepositoryOp[A]): M[A] = fa match { - case GetRepo(owner, repo, accessToken) ⇒ A.pureEval(Eval.later(repos.get(accessToken, owner, repo))) - case ListCommits(owner, repo, sha, path, author, since, until, pagination, accessToken) ⇒ A.pureEval(Eval.later(repos.listCommits(accessToken, owner, repo, sha, path, author, since, until, pagination))) - case ListContributors(owner, repo, anon, accessToken) ⇒ A.pureEval(Eval.later(repos.listContributors(accessToken, owner, repo, anon))) + case GetRepo(owner, repo, accessToken) ⇒ C.capture(repos.get(accessToken, owner, repo)) + case ListCommits(owner, repo, sha, path, author, since, until, pagination, accessToken) ⇒ C.capture(repos.listCommits(accessToken, owner, repo, sha, path, author, since, until, pagination)) + case ListContributors(owner, repo, anon, accessToken) ⇒ C.capture(repos.listContributors(accessToken, owner, repo, anon)) } } /** * Lifts User Ops to an effect capturing Monad such as Task via natural transformations */ - def userOpsInterpreter[M[_]](implicit A: ApplicativeError[M, Throwable]): UserOp ~> M = new (UserOp ~> M) { + def userOpsInterpreter[M[_]](implicit A: ApplicativeError[M, Throwable], C: Capture[M]): UserOp ~> M = new (UserOp ~> M) { val users = new Users() def apply[A](fa: UserOp[A]): M[A] = fa match { - case GetUser(username, accessToken) ⇒ A.pureEval(Eval.later(users.get(accessToken, username))) - case GetAuthUser(accessToken) ⇒ A.pureEval(Eval.later(users.getAuth(accessToken))) - case GetUsers(since, pagination, accessToken) ⇒ A.pureEval(Eval.later(users.getUsers(accessToken, since, pagination))) + case GetUser(username, accessToken) ⇒ C.capture(users.get(accessToken, username)) + case GetAuthUser(accessToken) ⇒ C.capture(users.getAuth(accessToken)) + case GetUsers(since, pagination, accessToken) ⇒ C.capture(users.getUsers(accessToken, since, pagination)) } } /** * Lifts Auth Ops to an effect capturing Monad such as Task via natural transformations */ - def authOpsInterpreter[M[_]](implicit A: ApplicativeError[M, Throwable]): AuthOp ~> M = new (AuthOp ~> M) { + def authOpsInterpreter[M[_]](implicit A: ApplicativeError[M, Throwable], C: Capture[M]): AuthOp ~> M = new (AuthOp ~> M) { val auth = new Auth() def apply[A](fa: AuthOp[A]): M[A] = fa match { - case NewAuth(username, password, scopes, note, client_id, client_secret) ⇒ A.pureEval(Eval.later(auth.newAuth(username, password, scopes, note, client_id, client_secret))) - case AuthorizeUrl(client_id, redirect_uri, scopes) ⇒ A.pureEval(Eval.later(auth.authorizeUrl(client_id, redirect_uri, scopes))) - case GetAccessToken(client_id, client_secret, code, redirect_uri, state) ⇒ A.pureEval(Eval.later(auth.getAccessToken(client_id, client_secret, code, redirect_uri, state))) + case NewAuth(username, password, scopes, note, client_id, client_secret) ⇒ C.capture(auth.newAuth(username, password, scopes, note, client_id, client_secret)) + case AuthorizeUrl(client_id, redirect_uri, scopes) ⇒ C.capture(auth.authorizeUrl(client_id, redirect_uri, scopes)) + case GetAccessToken(client_id, client_secret, code, redirect_uri, state) ⇒ C.capture(auth.getAccessToken(client_id, client_secret, code, redirect_uri, state)) } } } - diff --git a/src/test/scala/github4s/integration/GHAuthSpec.scala b/src/test/scala/github4s/integration/GHAuthSpec.scala index 7df2f482e..7c1f4fab4 100644 --- a/src/test/scala/github4s/integration/GHAuthSpec.scala +++ b/src/test/scala/github4s/integration/GHAuthSpec.scala @@ -3,8 +3,8 @@ package github4s.integration import cats.Id import cats.scalatest.{ XorMatchers, XorValues } import github4s.Github._ -import github4s.implicits._ import github4s.Github +import github4s.testimplicits._ import github4s.utils.TestUtils import org.scalatest._ diff --git a/src/test/scala/github4s/integration/GHReposSpec.scala b/src/test/scala/github4s/integration/GHReposSpec.scala index c3dd5a06e..d31ab6042 100644 --- a/src/test/scala/github4s/integration/GHReposSpec.scala +++ b/src/test/scala/github4s/integration/GHReposSpec.scala @@ -4,7 +4,7 @@ import cats.Id import cats.scalatest.{ XorMatchers, XorValues } import github4s.Github._ import github4s.GithubResponses._ -import github4s.implicits._ +import github4s.testimplicits._ import github4s.Github import github4s.utils.TestUtils import org.scalatest.{ Matchers, FlatSpec } @@ -48,4 +48,4 @@ class GHReposSpec extends FlatSpec with Matchers with XorMatchers with XorValues response shouldBe left } -} \ No newline at end of file +} diff --git a/src/test/scala/github4s/integration/GHUsersSpec.scala b/src/test/scala/github4s/integration/GHUsersSpec.scala index c428ecf7a..29dac8890 100644 --- a/src/test/scala/github4s/integration/GHUsersSpec.scala +++ b/src/test/scala/github4s/integration/GHUsersSpec.scala @@ -3,7 +3,7 @@ package github4s.integration import cats.Id import cats.scalatest.{ XorMatchers, XorValues } import github4s.Github._ -import github4s.implicits._ +import github4s.testimplicits._ import github4s.Github import github4s.utils.TestUtils import org.scalatest._ From 915bd9a8db5b8059e1faf5fa246b7438d7349867 Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Wed, 12 Oct 2016 13:10:18 +0200 Subject: [PATCH 2/4] Bumps version --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 51b6a9cd4..c6c536f4b 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.6-SNAPSHOT" +version in ThisBuild := "0.7-SNAPSHOT" From 437741da30bd8fa63c244ea33076a8558389843c Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Wed, 12 Oct 2016 13:24:45 +0200 Subject: [PATCH 3/4] Implements tailRecM for MonadError at scalaz module --- project/build.properties | 2 +- scalaz/src/main/scala/github4s/scalaz/Implicits.scala | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/project/build.properties b/project/build.properties index d638b4f34..13d3ee7b2 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version = 0.13.8 \ No newline at end of file +sbt.version = 0.13.12 \ No newline at end of file diff --git a/scalaz/src/main/scala/github4s/scalaz/Implicits.scala b/scalaz/src/main/scala/github4s/scalaz/Implicits.scala index af8c9feca..ecadc2866 100644 --- a/scalaz/src/main/scala/github4s/scalaz/Implicits.scala +++ b/scalaz/src/main/scala/github4s/scalaz/Implicits.scala @@ -1,11 +1,11 @@ package github4s.scalaz -import cats.MonadError +import cats.{ MonadError, FlatMap } import scalaz.concurrent.Task object implicits { - implicit val g4sTaskMonadError: MonadError[Task, Throwable] = new MonadError[Task, Throwable] { + implicit def g4sTaskMonadError(implicit FM: FlatMap[Task]): MonadError[Task, Throwable] = new MonadError[Task, Throwable] { override def pure[A](x: A): Task[A] = Task.now(x) @@ -13,6 +13,8 @@ object implicits { override def flatMap[A, B](fa: Task[A])(ff: A ⇒ Task[B]): Task[B] = fa.flatMap(ff) + override def tailRecM[A, B](a: A)(f: A ⇒ Task[Either[A, B]]): Task[B] = FM.tailRecM(a)(f) + override def raiseError[A](e: Throwable): Task[A] = Task.fail(e) override def handleErrorWith[A](fa: Task[A])(f: Throwable ⇒ Task[A]): Task[A] = fa.handleWith({ case x ⇒ f(x) }) From 7f056f8b83c7ad022c056951a170910ee323a54c Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Wed, 12 Oct 2016 15:49:26 +0200 Subject: [PATCH 4/4] Upgrades scalaz and changes the base impl for tailRecM --- build.sbt | 2 +- docs/src/tut/docs.md | 2 +- .../scala/github4s/scalaz/Implicits.scala | 20 ++++++++++++--- src/main/scala/github4s/Implicits.scala | 25 ++++++++++--------- .../free/interpreters/Interpreters.scala | 4 +-- .../github4s/integration/GHAuthSpec.scala | 2 +- .../github4s/integration/GHReposSpec.scala | 2 +- .../github4s/integration/GHUsersSpec.scala | 2 +- 8 files changed, 37 insertions(+), 22 deletions(-) diff --git a/build.sbt b/build.sbt index bd234ce8d..766b5b85f 100644 --- a/build.sbt +++ b/build.sbt @@ -86,7 +86,7 @@ lazy val docs = (project in file("docs")) .dependsOn(scalaz) lazy val scalazDependencies = libraryDependencies ++= Seq( - "org.scalaz" %% "scalaz-concurrent" % "7.1.4" + "org.scalaz" %% "scalaz-concurrent" % "7.3.0-M5" ) lazy val scalazSettings = buildSettings ++ scalazDependencies ++ scalariformSettings diff --git a/docs/src/tut/docs.md b/docs/src/tut/docs.md index 1445c6abd..15abe70b4 100755 --- a/docs/src/tut/docs.md +++ b/docs/src/tut/docs.md @@ -61,7 +61,7 @@ val u2 = Github(accessToken).users.get("raulraja").exec[Id] WIP: With `Future` ```tut:silent -import cats.std.future._ +import github4s.implicits._ import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ diff --git a/scalaz/src/main/scala/github4s/scalaz/Implicits.scala b/scalaz/src/main/scala/github4s/scalaz/Implicits.scala index ecadc2866..e20258f88 100644 --- a/scalaz/src/main/scala/github4s/scalaz/Implicits.scala +++ b/scalaz/src/main/scala/github4s/scalaz/Implicits.scala @@ -1,11 +1,21 @@ package github4s.scalaz -import cats.{ MonadError, FlatMap } +import cats.implicits._ +import github4s.Github._ +import cats.{ MonadError, RecursiveTailRecM } import scalaz.concurrent.Task +import github4s.free.interpreters.Capture +import scalaz._ object implicits { - implicit def g4sTaskMonadError(implicit FM: FlatMap[Task]): MonadError[Task, Throwable] = new MonadError[Task, Throwable] { + implicit val taskCaptureInstance = new Capture[Task] { + override def capture[A](a: ⇒ A): Task[A] = Task.now(a) + } + + implicit val g4sTaskcatsRecursiveTailRecM: RecursiveTailRecM[Task] = new RecursiveTailRecM[Task] {} + + implicit def g4sTaskMonadError: MonadError[Task, Throwable] = new MonadError[Task, Throwable] { override def pure[A](x: A): Task[A] = Task.now(x) @@ -13,11 +23,15 @@ object implicits { override def flatMap[A, B](fa: Task[A])(ff: A ⇒ Task[B]): Task[B] = fa.flatMap(ff) - override def tailRecM[A, B](a: A)(f: A ⇒ Task[Either[A, B]]): Task[B] = FM.tailRecM(a)(f) + override def tailRecM[A, B](a: A)(f: A ⇒ Task[Either[A, B]]): Task[B] = + Task.tailrecM(a)(A ⇒ f(a) map (t ⇒ toScalazDisjunction(t))) override def raiseError[A](e: Throwable): Task[A] = Task.fail(e) override def handleErrorWith[A](fa: Task[A])(f: Throwable ⇒ Task[A]): Task[A] = fa.handleWith({ case x ⇒ f(x) }) + } + private[this] def toScalazDisjunction[A, B](disj: Either[A, B]): A \/ B = + disj.fold(l ⇒ -\/(l), r ⇒ \/-(r)) } diff --git a/src/main/scala/github4s/Implicits.scala b/src/main/scala/github4s/Implicits.scala index 83287394a..888828c30 100644 --- a/src/main/scala/github4s/Implicits.scala +++ b/src/main/scala/github4s/Implicits.scala @@ -1,29 +1,26 @@ package github4s import cats.implicits._ +import cats.instances.FutureInstances import cats.{ Monad, Id, Eval, MonadError, FlatMap } import github4s.free.interpreters._ import scala.concurrent.{ ExecutionContext, Future } -object implicits extends ProdInterpreters -object testimplicits extends TestInterpreters +object implicits extends Interpreters with EvalInstances with IdInstances with FutureInstances { -trait ProdInterpreters extends Interpreters[Eval] with EvalInstances { - - implicit val evalCaptureInstance = new Capture[Eval] { - override def capture[A](a: ⇒ A): Eval[A] = Eval.later(a) + //Future Capture evidence: + implicit val futureCaptureInstance = new Capture[Future] { + override def capture[A](a: ⇒ A): Future[A] = Future.successful(a) } -} -trait TestInterpreters extends Interpreters[Id] with IdInstances { - - implicit val idCaptureInstance = new Capture[Id] { - override def capture[A](a: ⇒ A): Id[A] = idMonad.pure(a) - } } trait EvalInstances { + implicit val evalCaptureInstance = new Capture[Eval] { + override def capture[A](a: ⇒ A): Eval[A] = Eval.later(a) + } + implicit def evalMonadError(implicit FM: FlatMap[Eval]): MonadError[Eval, Throwable] = new MonadError[Eval, Throwable] { override def pure[A](x: A): Eval[A] = Eval.now(x) @@ -52,6 +49,10 @@ trait EvalInstances { trait IdInstances { + implicit val idCaptureInstance = new Capture[Id] { + override def capture[A](a: ⇒ A): Id[A] = idMonad.pure(a) + } + implicit def idMonad(implicit I: Monad[Id], FM: FlatMap[Id]): MonadError[Id, Throwable] = new MonadError[Id, Throwable] { override def pure[A](x: A): Id[A] = I.pure(x) diff --git a/src/main/scala/github4s/free/interpreters/Interpreters.scala b/src/main/scala/github4s/free/interpreters/Interpreters.scala index 8c100aba1..a6d47e357 100644 --- a/src/main/scala/github4s/free/interpreters/Interpreters.scala +++ b/src/main/scala/github4s/free/interpreters/Interpreters.scala @@ -14,9 +14,9 @@ import simulacrum.typeclass def capture[A](a: ⇒ A): M[A] } -trait Interpreters[M[_]] { +trait Interpreters { - implicit def interpreters( + implicit def interpreters[M[_]]( implicit A: MonadError[M, Throwable], C: Capture[M] diff --git a/src/test/scala/github4s/integration/GHAuthSpec.scala b/src/test/scala/github4s/integration/GHAuthSpec.scala index 7c1f4fab4..c7df6b6db 100644 --- a/src/test/scala/github4s/integration/GHAuthSpec.scala +++ b/src/test/scala/github4s/integration/GHAuthSpec.scala @@ -4,7 +4,7 @@ import cats.Id import cats.scalatest.{ XorMatchers, XorValues } import github4s.Github._ import github4s.Github -import github4s.testimplicits._ +import github4s.implicits._ import github4s.utils.TestUtils import org.scalatest._ diff --git a/src/test/scala/github4s/integration/GHReposSpec.scala b/src/test/scala/github4s/integration/GHReposSpec.scala index d31ab6042..5df7445e7 100644 --- a/src/test/scala/github4s/integration/GHReposSpec.scala +++ b/src/test/scala/github4s/integration/GHReposSpec.scala @@ -4,7 +4,7 @@ import cats.Id import cats.scalatest.{ XorMatchers, XorValues } import github4s.Github._ import github4s.GithubResponses._ -import github4s.testimplicits._ +import github4s.implicits._ import github4s.Github import github4s.utils.TestUtils import org.scalatest.{ Matchers, FlatSpec } diff --git a/src/test/scala/github4s/integration/GHUsersSpec.scala b/src/test/scala/github4s/integration/GHUsersSpec.scala index 29dac8890..c428ecf7a 100644 --- a/src/test/scala/github4s/integration/GHUsersSpec.scala +++ b/src/test/scala/github4s/integration/GHUsersSpec.scala @@ -3,7 +3,7 @@ package github4s.integration import cats.Id import cats.scalatest.{ XorMatchers, XorValues } import github4s.Github._ -import github4s.testimplicits._ +import github4s.implicits._ import github4s.Github import github4s.utils.TestUtils import org.scalatest._