Skip to content

Commit

Permalink
Implement EitherT#leftFlatMap and EitherT#leftSemiflatMap (#1790)
Browse files Browse the repository at this point in the history
* Implement EitherT#leftFlatMap and EitherT#leftSemiflatMap

* Add additional tests for EitherT

* Rename tests

Tiny nit
  • Loading branch information
vendethiel authored and kailuowang committed Sep 29, 2017
1 parent b785cd5 commit 66b4ac7
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
12 changes: 12 additions & 0 deletions core/src/main/scala/cats/data/EitherT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {

def leftMap[C](f: A => C)(implicit F: Functor[F]): EitherT[F, C, B] = bimap(f, identity)

def leftFlatMap[BB >: B, D](f: A => EitherT[F, D, BB])(implicit F: Monad[F]): EitherT[F, D, BB] =
EitherT(F.flatMap(value) {
case Left(a) => f(a).value
case r@Right(_) => F.pure(r.leftCast)
})

def leftSemiflatMap[D](f: A => F[D])(implicit F: Monad[F]): EitherT[F, D, B] =
EitherT(F.flatMap(value) {
case Left(a) => F.map(f(a)) { d => Left(d) }
case r@Right(_) => F.pure(r.leftCast)
})

def compare(that: EitherT[F, A, B])(implicit o: Order[F[Either[A, B]]]): Int =
o.compare(value, that.value)

Expand Down
24 changes: 24 additions & 0 deletions tests/src/test/scala/cats/tests/EitherTTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -434,4 +434,28 @@ class EitherTTests extends CatsSuite {
} yield s1 ++ s2
}

test("leftFlatMap consistent with leftMap") {
forAll { (eithert: EitherT[List, String, Int], f: String => String) =>
eithert.leftFlatMap(v => EitherT.left[Int](List(f(v)))) should ===(eithert.leftMap(f))
}
}

test("leftFlatMap consistent with swap and then flatMap") {
forAll { (eithert: EitherT[List, String, Int], f: String => EitherT[List, String, Int]) =>
eithert.leftFlatMap(f) should ===(eithert.swap.flatMap(a => f(a).swap).swap)
}
}

test("leftSemiflatMap consistent with leftMap") {
forAll { (eithert: EitherT[List, String, Int], f: String => String) =>
eithert.leftSemiflatMap(v => List(f(v))) should ===(eithert.leftMap(f))
}
}

test("leftSemiflatmap consistent with swap and the semiflatMap") {
forAll { (eithert: EitherT[List, String, Int], f: String => List[String]) =>
eithert.leftSemiflatMap(f) should ===(eithert.swap.semiflatMap(a => f(a)).swap)
}
}

}

0 comments on commit 66b4ac7

Please sign in to comment.