diff --git a/build.sbt b/build.sbt index c7241da..dfc9422 100644 --- a/build.sbt +++ b/build.sbt @@ -4,21 +4,21 @@ lazy val cats = (project in file(".")) .settings( organization := "org.scala-exercises", name := "exercises-cats", - scalaVersion := "2.11.7", - version := "0.2.5-SNAPSHOT", + scalaVersion := "2.11.8", + version := "0.3.0-SNAPSHOT", resolvers ++= Seq( Resolver.sonatypeRepo("snapshots"), Resolver.sonatypeRepo("releases") ), libraryDependencies ++= Seq( - "org.typelevel" %% "cats-core" % "0.4.1", + "org.typelevel" %% "cats-core" % "0.7.2", "com.chuusai" %% "shapeless" % "2.2.5", "org.scalatest" %% "scalatest" % "2.2.4", "org.scala-exercises" %% "exercise-compiler" % version.value, "org.scala-exercises" %% "definitions" % version.value, "org.scalacheck" %% "scalacheck" % "1.12.5", "com.github.alexarchambault" %% "scalacheck-shapeless_1.12" % "0.3.1", - compilerPlugin("org.spire-math" %% "kind-projector" % "0.7.1") + compilerPlugin("org.spire-math" %% "kind-projector" % "0.9.0") ) ) diff --git a/project/build.properties b/project/build.properties index 176a863..7d789d4 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.9 \ No newline at end of file +sbt.version=0.13.12 \ No newline at end of file diff --git a/project/plugins.sbt b/project/plugins.sbt index 3eaab73..eb6e308 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,5 +2,5 @@ resolvers ++= Seq( Resolver.sonatypeRepo("snapshots") ) -addSbtPlugin("org.scala-exercises" % "sbt-exercise" % "0.2.5-SNAPSHOT", "0.13", "2.10") +addSbtPlugin("org.scala-exercises" % "sbt-exercise" % "0.3.0-SNAPSHOT", "0.13", "2.10") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") diff --git a/src/main/scala/catslib/Applicative.scala b/src/main/scala/catslib/Applicative.scala index e76f403..502ad1c 100644 --- a/src/main/scala/catslib/Applicative.scala +++ b/src/main/scala/catslib/Applicative.scala @@ -3,7 +3,7 @@ package catslib import org.scalatest._ import cats._ -import cats.std.all._ +import cats.implicits._ /** `Applicative` extends `Apply` by adding a single method, `pure`: * @@ -25,7 +25,7 @@ object ApplicativeSection extends FlatSpec with Matchers with org.scalaexercises */ def pureMethod(res0: Option[Int], res1: List[Int]) = { import cats._ - import cats.std.all._ + import cats.implicits._ Applicative[Option].pure(1) should be(res0) Applicative[List].pure(1) should be(res1) diff --git a/src/main/scala/catslib/Apply.scala b/src/main/scala/catslib/Apply.scala index 48a2a5b..52e2dee 100644 --- a/src/main/scala/catslib/Apply.scala +++ b/src/main/scala/catslib/Apply.scala @@ -4,9 +4,7 @@ import org.scalatest._ import ApplyHelpers._ import cats._ -import cats.std.all._ -import cats.syntax.apply._ -import cats.syntax.cartesian._ +import cats.implicits._ /** `Apply` extends the `Functor` type class (which features the familiar `map` * function) with a new function `ap`. The `ap` function is similar to `map` @@ -48,7 +46,7 @@ object ApplySection extends FlatSpec with Matchers with org.scalaexercises.defin * Since `Apply` extends `Functor`, we can use the `map` method from `Functor`: */ def applyExtendsFunctor(res0: Option[String], res1: Option[Int], res2: Option[Int]) = { - import cats.std.all._ + import cats.implicits._ val intToString: Int ⇒ String = _.toString val double: Int ⇒ Int = _ * 2 @@ -124,7 +122,7 @@ object ApplySection extends FlatSpec with Matchers with org.scalaexercises.defin * * The `|@|` operator offers an alternative syntax for the higher-arity `Apply` * functions (`apN`, `mapN` and `tupleN`). - * In order to use it, first import `cats.syntax.all._` or `cats.syntax.apply._`. + * In order to use it, first import `cats.implicits._`. * * All instances created by `|@|` have `map`, `ap`, and `tupled` methods of the appropriate arity: * diff --git a/src/main/scala/catslib/Foldable.scala b/src/main/scala/catslib/Foldable.scala index 100f9f6..919b47e 100644 --- a/src/main/scala/catslib/Foldable.scala +++ b/src/main/scala/catslib/Foldable.scala @@ -144,7 +144,7 @@ object FoldableSection extends FlatSpec with Matchers with org.scalaexercises.de * */ def foldableTraverse(res0: Option[Unit], res1: Option[Unit]) = { - import cats.std.all._ + import cats.implicits._ import cats.data.Xor def parseInt(s: String): Option[Int] = diff --git a/src/main/scala/catslib/FunctorSection.scala b/src/main/scala/catslib/FunctorSection.scala index e3d30cc..e3b9e47 100644 --- a/src/main/scala/catslib/FunctorSection.scala +++ b/src/main/scala/catslib/FunctorSection.scala @@ -3,8 +3,7 @@ package catslib import org.scalatest._ import cats._ -import cats.std.option._ -import cats.std.list._ +import cats.implicits._ /** A `Functor` is a ubiquitous type class involving types that have one * "hole", i.e. types which have the shape `F[?]`, such as `Option`, diff --git a/src/main/scala/catslib/Monad.scala b/src/main/scala/catslib/Monad.scala index 4e99f6f..92b7b44 100644 --- a/src/main/scala/catslib/Monad.scala +++ b/src/main/scala/catslib/Monad.scala @@ -52,7 +52,7 @@ object MonadSection extends FlatSpec with Matchers with org.scalaexercises.defin */ def monadInstances(res0: Option[Int]) = { import cats._ - import cats.std.option._ + import cats.implicits._ Monad[Option].pure(42) should be(res0) } @@ -76,7 +76,7 @@ object MonadSection extends FlatSpec with Matchers with org.scalaexercises.defin */ def monadFlatmap(res0: List[Int]) = { import cats._ - import cats.std.list._ + import cats.implicits._ Monad[List].flatMap(List(1, 2, 3))(x ⇒ List(x, x)) should be(res0) } @@ -89,7 +89,7 @@ object MonadSection extends FlatSpec with Matchers with org.scalaexercises.defin */ def monadIfm(res0: Option[String], res1: List[Int]) = { import cats._ - import cats.std.all._ + import cats.implicits._ Monad[Option].ifM(Option(true))(Option("truthy"), Option("falsy")) should be(res0) Monad[List].ifM(List(true, false, true))(List(1, 2), List(3, 4)) should be(res1) @@ -106,18 +106,20 @@ object MonadSection extends FlatSpec with Matchers with org.scalaexercises.defin * * {{{ * case class OptionT[F[_], A](value: F[Option[A]]) - * + * implicit def optionTMonad[F[_]](implicit F : Monad[F]) = { - * new Monad[OptionT[F, ?]] { - * def pure[A](a: A): OptionT[F, A] = OptionT(F.pure(Some(a))) - * def flatMap[A, B](fa: OptionT[F, A])(f: A => OptionT[F, B]): OptionT[F, B] = - * OptionT { - * F.flatMap(fa.value) { - * case None => F.pure(None) - * case Some(a) => f(a).value - * } - * } - * } + * new Monad[OptionT[F, ?]] { + * def pure[A](a: A): OptionT[F, A] = OptionT(F.pure(Some(a))) + * def flatMap[A, B](fa: OptionT[F, A])(f: A => OptionT[F, B]): OptionT[F, B] = + * OptionT { + * F.flatMap(fa.value) { + * case None => F.pure(None) + * case Some(a) => f(a).value + * } + * } + * def tailRecM[A, B](a: A)(f: A => OptionT[F, Either[A, B]]): OptionT[F, B] = + * defaultTailRecM(a)(f) + * } * } * }}} * @@ -126,7 +128,7 @@ object MonadSection extends FlatSpec with Matchers with org.scalaexercises.defin * */ def monadComposition(res0: List[Option[Int]]) = { - import cats.std.list._ + import cats.implicits._ optionTMonad[List].pure(42) should be(OptionT(res0)) } diff --git a/src/main/scala/catslib/MonadHelpers.scala b/src/main/scala/catslib/MonadHelpers.scala index 631f930..cee19c5 100644 --- a/src/main/scala/catslib/MonadHelpers.scala +++ b/src/main/scala/catslib/MonadHelpers.scala @@ -15,6 +15,9 @@ object MonadHelpers { case Some(a) ⇒ f(a).value } } + + def tailRecM[A, B](a: A)(f: A => OptionT[F, Either[A, B]]): OptionT[F, B] = + defaultTailRecM(a)(f) } } } diff --git a/src/main/scala/catslib/Monoid.scala b/src/main/scala/catslib/Monoid.scala index 9afe274..1a33c41 100644 --- a/src/main/scala/catslib/Monoid.scala +++ b/src/main/scala/catslib/Monoid.scala @@ -3,8 +3,7 @@ package catslib import org.scalatest._ import cats._ -import cats.std.all._ -import cats.syntax.all._ +import cats.implicits._ /** `Monoid` extends the `Semigroup` type class, adding an * `empty` method to semigroup's `combine`. The `empty` method must return a @@ -30,8 +29,7 @@ object MonoidSection extends FlatSpec with Matchers with org.scalaexercises.defi * * {{{ * import cats._ - * import cats.std.all._ - * import cats.syntax.all._ + * import cats.implicits._ * }}} * * And let's see the implicit instance of `Monoid[String]` in action. diff --git a/src/main/scala/catslib/Traverse.scala b/src/main/scala/catslib/Traverse.scala index ad2c549..f7ecbe0 100644 --- a/src/main/scala/catslib/Traverse.scala +++ b/src/main/scala/catslib/Traverse.scala @@ -3,8 +3,7 @@ package catslib import org.scalatest._ import cats.data.{ Xor, ValidatedNel } -import cats.std.all._ -import cats.syntax.all._ +import cats.implicits._ import TraverseHelpers._ @@ -98,8 +97,7 @@ object TraverseSection extends FlatSpec with Matchers with org.scalaexercises.de * {{{ * import cats.Semigroup * import cats.data.{NonEmptyList, OneAnd, Validated, ValidatedNel, Xor} - * import cats.std.list._ - * import cats.syntax.traverse._ + * import cats.implicits._ * * def parseIntXor(s: String): Xor[NumberFormatException, Int] = * Xor.catchOnly[NumberFormatException](s.toInt) @@ -210,7 +208,7 @@ object TraverseSection extends FlatSpec with Matchers with org.scalaexercises.de * */ def sequencing(res0: Option[List[Int]], res1: Option[List[Int]]) = { - import cats.std.option._ + import cats.implicits._ List(Option(1), Option(2), Option(3)).traverse(identity) should be(res0) List(Option(1), None, Option(3)).traverse(identity) should be(res1) @@ -236,7 +234,7 @@ object TraverseSection extends FlatSpec with Matchers with org.scalaexercises.de * If we traverse using this, we end up with a funny type. * * {{{ - * import cats.std.future._ + * import cats.implicits._ * import scala.concurrent.ExecutionContext.Implicits.global * * def writeManyToStore(data: List[Data]) = @@ -252,7 +250,7 @@ object TraverseSection extends FlatSpec with Matchers with org.scalaexercises.de * */ def traversingForEffects(res0: Option[Unit], res1: Option[Unit]) = { - import cats.syntax.foldable._ + import cats.implicits._ List(Option(1), Option(2), Option(3)).sequence_ should be(res0) List(Option(1), None, Option(3)).sequence_ should be(res1) diff --git a/src/main/scala/catslib/TraverseHelpers.scala b/src/main/scala/catslib/TraverseHelpers.scala index 677773b..97fa48d 100644 --- a/src/main/scala/catslib/TraverseHelpers.scala +++ b/src/main/scala/catslib/TraverseHelpers.scala @@ -3,8 +3,7 @@ package catslib object TraverseHelpers { import cats.Semigroup import cats.data.{ NonEmptyList, OneAnd, Validated, ValidatedNel, Xor } - import cats.std.list._ - import cats.syntax.traverse._ + import cats.implicits._ def parseIntXor(s: String): Xor[NumberFormatException, Int] = Xor.catchOnly[NumberFormatException](s.toInt) diff --git a/src/main/scala/catslib/Validated.scala b/src/main/scala/catslib/Validated.scala index 0875fbf..4fb0a9d 100644 --- a/src/main/scala/catslib/Validated.scala +++ b/src/main/scala/catslib/Validated.scala @@ -151,7 +151,7 @@ import ValidatedHelpers._ * {{{ * import cats.SemigroupK * import cats.data.NonEmptyList - * import cats.std.list._ + * import cats.implicits._ * * implicit val nelSemigroup: Semigroup[NonEmptyList[ConfigError]] = * SemigroupK[NonEmptyList].algebra[ConfigError] @@ -192,7 +192,7 @@ object ValidatedSection extends FlatSpec with Matchers with org.scalaexercises.d import cats.data.NonEmptyList invalid.isValid should be(res0) - val errors = NonEmptyList(MissingConfig("url"), ParseError("port")) + val errors = NonEmptyList(MissingConfig("url"), List(ParseError("port"))) invalid == Validated.invalid(errors) should be(res1) } diff --git a/src/main/scala/catslib/ValidatedHelpers.scala b/src/main/scala/catslib/ValidatedHelpers.scala index fb76d45..c5c17ac 100644 --- a/src/main/scala/catslib/ValidatedHelpers.scala +++ b/src/main/scala/catslib/ValidatedHelpers.scala @@ -5,7 +5,7 @@ import cats.data.NonEmptyList import cats.data.Validated import cats.data.Validated.{ Invalid, Valid } import cats.data.Xor -import cats.std.list._ +import cats.implicits._ object ValidatedHelpers { case class ConnectionParams(url: String, port: Int) @@ -59,7 +59,7 @@ object ValidatedHelpers { import cats.SemigroupK import cats.data.NonEmptyList - import cats.std.list._ + import cats.implicits._ implicit val nelSemigroup: Semigroup[NonEmptyList[ConfigError]] = SemigroupK[NonEmptyList].algebra[ConfigError] diff --git a/src/main/scala/catslib/XorSection.scala b/src/main/scala/catslib/XorSection.scala index 0583d5e..cb9b0d7 100644 --- a/src/main/scala/catslib/XorSection.scala +++ b/src/main/scala/catslib/XorSection.scala @@ -448,11 +448,11 @@ object XorSection extends FlatSpec with Matchers with org.scalaexercises.definit /** = Additional syntax = * - * For using Xor's syntax on arbitrary data types, you can import `cats.syntax.xor._`. This will + * For using Xor's syntax on arbitrary data types, you can import `cats.implicits._`. This will * make possible to use the `left` and `right` methods: * * {{{ - * import cats.syntax.xor._ + * import cats.implicits._ * * val right: Xor[String, Int] = 7.right[String] * @@ -463,7 +463,7 @@ object XorSection extends FlatSpec with Matchers with org.scalaexercises.definit * */ def xorSyntax(res0: String Xor Int) = { - import cats.syntax.xor._ + import cats.implicits._ val right: Xor[String, Int] = 42.right[String] right should be(res0)