Skip to content

Commit

Permalink
Merge pull request typelevel#1013 from julienrf/monadError-filterOrElse
Browse files Browse the repository at this point in the history
Add MonadError.ensure method
  • Loading branch information
non committed May 31, 2016
2 parents 92269f7 + 1752755 commit 04b2501
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 1 deletion.
10 changes: 9 additions & 1 deletion core/src/main/scala/cats/MonadError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ package cats
*
* This type class allows one to abstract over error-handling monads.
*/
trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F]
trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] {

/**
* Turns a successful value into an error if it does not satisfy a given predicate.
*/
def ensure[A](fa: F[A])(error: => E)(predicate: A => Boolean): F[A] =
flatMap(fa)(a => if (predicate(a)) pure(a) else raiseError(error))

}

object MonadError {
def apply[F[_], E](implicit F: MonadError[F, E]): MonadError[F, E] = F
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/scala/cats/data/Xor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ private[data] sealed abstract class XorInstances extends XorInstances1 {
fab recover pf
override def recoverWith[B](fab: A Xor B)(pf: PartialFunction[A, A Xor B]): A Xor B =
fab recoverWith pf
override def ensure[B](fab: A Xor B)(error: => A)(predicate: B => Boolean): A Xor B =
fab.ensure(error)(predicate)
}
}

Expand Down
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 @@ -22,6 +22,7 @@ trait AllSyntax
with InvariantSyntax
with ListSyntax
with MonadCombineSyntax
with MonadErrorSyntax
with MonadFilterSyntax
with OptionSyntax
with OrderSyntax
Expand Down
16 changes: 16 additions & 0 deletions core/src/main/scala/cats/syntax/monadError.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cats
package syntax

trait MonadErrorSyntax {

implicit def monadErrorSyntax[F[_], E, A](fa: F[A])(implicit F: MonadError[F, E]): MonadErrorOps[F, E, A] =
new MonadErrorOps(fa)

}

final class MonadErrorOps[F[_], E, A](fa: F[A])(implicit F: MonadError[F, E]) {

def ensure(error: => E)(predicate: A => Boolean): F[A] =
F.ensure(fa)(error)(predicate)

}
22 changes: 22 additions & 0 deletions tests/src/test/scala/cats/tests/MonadErrorSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cats
package tests

class MonadErrorSuite extends CatsSuite {

val successful: Option[Int] = 42.some
val failed: Option[Int] = None

test("ensure raises an error if the predicate fails") {
successful.ensure(())(i => false) should === (None)
}

test("ensure returns the successful value if the predicate succeeds") {
successful.ensure(())(i => true) should === (successful)
}

test("ensure returns the failure, when applied to a failure") {
failed.ensure(())(i => false) should === (failed)
failed.ensure(())(i => true) should === (failed)
}

}

0 comments on commit 04b2501

Please sign in to comment.