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 ec384d0 commit c005111
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 @@ -6,6 +6,7 @@ object implicits
with syntax.AllSyntaxBinCompat1
with syntax.AllSyntaxBinCompat2
with syntax.AllSyntaxBinCompat3
with syntax.AllSyntaxBinCompat4
with instances.AllInstances
with instances.AllInstancesBinCompat0
with instances.AllInstancesBinCompat1
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/scala/cats/syntax/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ abstract class AllSyntaxBinCompat
with AllSyntaxBinCompat1
with AllSyntaxBinCompat2
with AllSyntaxBinCompat3
with AllSyntaxBinCompat4

trait AllSyntax
extends AlternativeSyntax
Expand Down Expand Up @@ -77,3 +78,5 @@ trait AllSyntaxBinCompat2
with ValidatedSyntaxBincompat0

trait AllSyntaxBinCompat3 extends UnorderedFoldableSyntax with Function1Syntax

trait AllSyntaxBinCompat4 extends FoldableSyntaxBinCompat0
38 changes: 38 additions & 0 deletions core/src/main/scala/cats/syntax/foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,5 +190,43 @@ final class FoldableOps[F[_], A](private val fa: F[A]) extends AnyVal {
case None acc
}
)
}

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

final class FoldableOpsBinCompat0[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])
}
)
}
}

0 comments on commit c005111

Please sign in to comment.