Skip to content

Commit

Permalink
Moving binary incompatible change out into FoldableSyntaxBinCompat0
Browse files Browse the repository at this point in the history
  • Loading branch information
Devon Stewart committed Dec 28, 2018
1 parent a831bf4 commit 8e99343
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 32 deletions.
32 changes: 0 additions & 32 deletions core/src/main/scala/cats/Foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -506,38 +506,6 @@ import Foldable.sentinel
)
}

/**
* Separate this Foldable into a Tuple by an effectful separating function `A => G[Either[B, C]]`
* Equivalent to `Bitraversable#traverse` over `Alternative#separate`
*
* {{{
* scala> import cats.implicits._
* scala> val list = List(1,2,3,4)
* scala> val partitioned1 = Foldable[List].partitionEitherM(list)(a => if (a % 2 == 0) Eval.now(Either.left[String, Int](a.toString)) else Eval.now(Either.right[String, Int](a)))
* Since `Eval.now` yields a lazy computation, we need to force it to inspect the result:
* scala> partitioned1.value
* res0: (List[String], List[Int]) = (List(2, 4),List(1, 3))
* scala> val partitioned2 = Foldable[List].partitionEitherM(list)(a => Eval.later(Either.right(a * 4)))
* scala> partitioned2.value
* res1: (List[Nothing], List[Int]) = (List(),List(4, 8, 12, 16))
* }}}
*/
def partitionEitherM[G[_], A, B, C](fa: F[A])(f: A => G[Either[B, C]])(implicit A: Alternative[F],
M: Monad[G]): G[(F[B], F[C])] = {
import cats.instances.tuple._

implicit val mb: Monoid[F[B]] = A.algebra[B]
implicit val mc: Monoid[F[C]] = A.algebra[C]

foldMapM[G, A, (F[B], F[C])](fa)(
a =>
M.map(f(a)) {
case Right(c) => (A.empty[B], A.pure(c))
case Left(b) => (A.pure(b), A.empty[C])
}
)
}

/**
* Convert F[A] to a List[A], only including elements which match `p`.
*/
Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala/cats/implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ object implicits
with syntax.AllSyntaxBinCompat2
with syntax.AllSyntaxBinCompat3
with syntax.AllSyntaxBinCompat4
with syntax.AllSyntaxBinCompat5
with instances.AllInstances
with instances.AllInstancesBinCompat0
with instances.AllInstancesBinCompat1
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/scala/cats/syntax/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,5 @@ trait AllSyntaxBinCompat4
with ParallelApplySyntax
with FoldableSyntaxBinCompat0
with ReducibleSyntaxBinCompat0

trait AllSyntaxBinCompat5 extends FoldableSyntaxBinCompat1
39 changes: 39 additions & 0 deletions core/src/main/scala/cats/syntax/foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ trait FoldableSyntaxBinCompat0 {
new FoldableOps0[F, A](fa)
}

trait FoldableSyntaxBinCompat1 {
implicit final def catsSyntaxFoldableBinCompat0[F[_]](fa: Foldable[F]): FoldableOpsBinCompat1[F] =
new FoldableOpsBinCompat1(fa)
}

final class NestedFoldableOps[F[_], G[_], A](private val fga: F[G[A]]) extends AnyVal {
def sequence_(implicit F: Foldable[F], G: Applicative[G]): G[Unit] = F.sequence_(fga)

Expand Down Expand Up @@ -195,7 +200,41 @@ final class FoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
case None acc
}
)
}

final class FoldableOpsBinCompat1[F[_]](private val F: Foldable[F]) extends AnyVal {

/**
* Separate this Foldable into a Tuple by an effectful separating function `A => G[Either[B, C]]`
* Equivalent to `Bitraversable#traverse` over `Alternative#separate`
*
* {{{
* scala> import cats.implicits._, cats.Foldable, cats.Eval
* scala> val list = List(1,2,3,4)
* scala> val partitioned1 = Foldable[List].partitionEitherM(list)(a => if (a % 2 == 0) Eval.now(Either.left[String, Int](a.toString)) else Eval.now(Either.right[String, Int](a)))
* Since `Eval.now` yields a lazy computation, we need to force it to inspect the result:
* scala> partitioned1.value
* res0: (List[String], List[Int]) = (List(2, 4),List(1, 3))
* scala> val partitioned2 = Foldable[List].partitionEitherM(list)(a => Eval.later(Either.right(a * 4)))
* scala> partitioned2.value
* res1: (List[Nothing], List[Int]) = (List(),List(4, 8, 12, 16))
* }}}
*/
def partitionEitherM[G[_], A, B, C](fa: F[A])(f: A => G[Either[B, C]])(implicit A: Alternative[F],
M: Monad[G]): G[(F[B], F[C])] = {
import cats.instances.tuple._

implicit val mb: Monoid[F[B]] = A.algebra[B]
implicit val mc: Monoid[F[C]] = A.algebra[C]

F.foldMapM[G, A, (F[B], F[C])](fa)(
a =>
M.map(f(a)) {
case Right(c) => (A.empty[B], A.pure(c))
case Left(b) => (A.pure(b), A.empty[C])
}
)
}
}

final class FoldableOps0[F[_], A](val fa: F[A]) extends AnyVal {
Expand Down

0 comments on commit 8e99343

Please sign in to comment.