From 7d423672c814bf40f36773bbbe68471c915ed949 Mon Sep 17 00:00:00 2001 From: Chris Davenport Date: Fri, 15 Dec 2017 18:05:44 -0500 Subject: [PATCH 1/2] Add Function for CoflatMap for Applicative --- core/src/main/scala/cats/Applicative.scala | 8 ++++++++ .../test/scala/cats/tests/ApplicativeSuite.scala | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index 47300f7522..b8d81a1fd6 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -207,6 +207,14 @@ object Applicative { */ implicit def catsApplicativeForArrow[F[_, _], A](implicit F: Arrow[F]): Applicative[F[A, ?]] = new ArrowApplicative[F, A](F) + + + def coflatMap[F[_]](implicit F: Applicative[F]): CoflatMap[F] = + new CoflatMap[F] { + def coflatMap[A, B](fa: F[A])(f: F[A] => B): F[B] = F.pure(f(fa)) + def map[A, B](fa: F[A])(f: A => B): F[B] = F.map(fa)(f) + } + } private[cats] class ApplicativeMonoid[F[_], A](f: Applicative[F], monoid: Monoid[A]) extends ApplySemigroup(f, monoid) with Monoid[F[A]] { diff --git a/tests/src/test/scala/cats/tests/ApplicativeSuite.scala b/tests/src/test/scala/cats/tests/ApplicativeSuite.scala index 11b0f0cce0..021dd29c2c 100644 --- a/tests/src/test/scala/cats/tests/ApplicativeSuite.scala +++ b/tests/src/test/scala/cats/tests/ApplicativeSuite.scala @@ -2,6 +2,9 @@ package cats package tests import cats.Applicative +import cats.data.{Validated, Const} +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.CoflatMapTests class ApplicativeSuite extends CatsSuite { @@ -36,4 +39,14 @@ class ApplicativeSuite extends CatsSuite { } } + implicit val listwrapperApplicative = ListWrapper.applicative + implicit val listwrapperCoflatMap = Applicative.coflatMap[ListWrapper] + checkAll("Applicative[ListWrapper].coflatMap", CoflatMapTests[ListWrapper].coflatMap[String, String, String]) + + implicit val validatedCoflatMap = Applicative.coflatMap[Validated[String, ?]] + checkAll("Applicative[Validated].coflatMap", CoflatMapTests[Validated[String, ?]].coflatMap[String, String, String]) + + implicit val constCoflatMap = Applicative.coflatMap[Const[String, ?]] + checkAll("Applicative[Const].coflatMap", CoflatMapTests[Const[String, ?]].coflatMap[String, String, String]) + } From 36b428ac5ec0897f9fdad1719604952fafad87f3 Mon Sep 17 00:00:00 2001 From: Chris Davenport Date: Fri, 15 Dec 2017 18:47:08 -0500 Subject: [PATCH 2/2] Add Documentation for Applicative coflatMap usage --- core/src/main/scala/cats/Applicative.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index b8d81a1fd6..93d2019ae9 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -209,6 +209,20 @@ object Applicative { new ArrowApplicative[F, A](F) + /** + * Creates a CoflatMap for an Applicative `F`. + * Cannot be implicit in 1.0 for Binary Compatibility Reasons + * + * Example: + * {{{ + * scala> import cats._ + * scala> import cats.implicits._ + * scala> val fa = Some(3) + * fa: Option[Int] = Some(3) + * scala> Applicative.coflatMap[Option].coflatten(fa) + * res0: Option[Option[Int]] = Some(Some(3)) + * }}} + */ def coflatMap[F[_]](implicit F: Applicative[F]): CoflatMap[F] = new CoflatMap[F] { def coflatMap[A, B](fa: F[A])(f: F[A] => B): F[B] = F.pure(f(fa))