Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add syntax for Bitraverse to allow traversal and sequencing of the left side #2606

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 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,4 @@ trait AllSyntaxBinCompat4
with ParallelApplySyntax
with FoldableSyntaxBinCompat0
with ReducibleSyntaxBinCompat0
with BitraverseSyntaxBinCompat0
61 changes: 61 additions & 0 deletions core/src/main/scala/cats/syntax/bitraverse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,64 @@ final class NestedBitraverseOps[F[_, _], G[_], A, B](private val fgagb: F[G[A],
def bisequence(implicit F: Bitraverse[F], G: Applicative[G]): G[F[A, B]] =
F.bisequence(fgagb)
}

trait BitraverseSyntaxBinCompat0 {
implicit final def catsSyntaxBitraverseBinCompat0[F[_, _]: Bitraverse, A, B](
fab: F[A, B]
): BitraverseOpsBinCompat0[F, A, B] =
new BitraverseOpsBinCompat0[F, A, B](fab)
implicit final def catsSyntaxLeftNestedBitraverse[F[_, _]: Bitraverse, G[_], A, B](
fgab: F[G[A], B]
): LeftNestedBitraverseOps[F, G, A, B] =
new LeftNestedBitraverseOps[F, G, A, B](fgab)
}

final class BitraverseOpsBinCompat0[F[_, _], A, B](val fab: F[A, B]) extends AnyVal {

/**
* Traverse over the left side of the structure.
* For the right side, use the standard `traverse` from [[cats.Traverse]].
*
* Example:
* {{{
* scala> import cats.implicits._
*
* scala> val intAndString: (Int, String) = (7, "test")
*
* scala> intAndString.leftTraverse(i => Option(i).filter(_ > 5))
* res1: Option[(Int, String)] = Some((7,test))
*
* scala> intAndString.leftTraverse(i => Option(i).filter(_ < 5))
* res2: Option[(Int, String)] = None
* }}}
*/
def leftTraverse[G[_], C](f: A => G[C])(implicit F: Bitraverse[F], G: Applicative[G]): G[F[C, B]] =
F.bitraverse(fab)(f, G.pure(_))
}

final class LeftNestedBitraverseOps[F[_, _], G[_], A, B](val fgab: F[G[A], B]) extends AnyVal {

/**
* Sequence the left side of the structure.
* For the right side, use the standard `sequence` from [[cats.Traverse]].
*
* Example:
* {{{
* scala> import cats.implicits._
*
* scala> val optionalErrorRight: Either[Option[String], Int] = Either.right(123)
* scala> optionalErrorRight.leftSequence
* res1: Option[Either[String, Int]] = Some(Right(123))
*
* scala> val optionalErrorLeftSome: Either[Option[String], Int] = Either.left(Some("something went wrong"))
* scala> optionalErrorLeftSome.leftSequence
* res2: Option[Either[String, Int]] = Some(Left(something went wrong))
*
* scala> val optionalErrorLeftNone: Either[Option[String], Int] = Either.left(None)
* scala> optionalErrorLeftNone.leftSequence
* res3: Option[Either[String,Int]] = None
* }}}
*/
def leftSequence(implicit F: Bitraverse[F], G: Applicative[G]): G[F[A, B]] =
F.bitraverse(fgab)(identity, G.pure(_))
}
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ package object syntax {
object bifunctor extends BifunctorSyntax
object bifoldable extends BifoldableSyntax
object binested extends BinestedSyntax
object bitraverse extends BitraverseSyntax
object bitraverse extends BitraverseSyntax with BitraverseSyntaxBinCompat0
@deprecated("use cats.syntax.semigroupal instead", "1.0.0-RC1")
object cartesian extends SemigroupalSyntax
object choice extends ChoiceSyntax
Expand Down
4 changes: 4 additions & 0 deletions tests/src/test/scala/cats/tests/SyntaxSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,13 @@ object SyntaxSuite

val fab = mock[F[A, B]]
val gfcd = fab.bitraverse(f, g)
val gfcb = fab.leftTraverse(f)

val fgagb = mock[F[G[A], G[B]]]
val gfab = fgagb.bisequence

val fgab = mock[F[G[A], B]]
val gfab2 = fgab.leftSequence
}

def testAlternativeMonad[F[_]: Alternative: Monad, G[_]: Foldable, H[_, _]: Bifoldable, A, B]: Unit = {
Expand Down