Skip to content

Commit

Permalink
Merge pull request #947 from davegurnell/master
Browse files Browse the repository at this point in the history
Syntax for ApplicativeError
  • Loading branch information
adelbertc committed Mar 28, 2016
2 parents 6e86bcf + 471b648 commit 79d40a9
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 0 deletions.
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 @@ -3,6 +3,7 @@ package syntax

trait AllSyntax
extends ApplicativeSyntax
with ApplicativeErrorSyntax
with ApplySyntax
with BifunctorSyntax
with BifoldableSyntax
Expand Down
37 changes: 37 additions & 0 deletions core/src/main/scala/cats/syntax/applicativeError.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cats
package syntax

import cats.data.{Xor, XorT}

trait ApplicativeErrorSyntax {
implicit def applicativeErrorIdSyntax[E](e: E): ApplicativeErrorIdOps[E] =
new ApplicativeErrorIdOps(e)

implicit def applicativeErrorSyntax[F[_, _], E, A](fa: F[E, A])(implicit F: ApplicativeError[F[E, ?], E]): ApplicativeErrorOps[F[E, ?], E, A] =
new ApplicativeErrorOps[F[E, ?], E, A](fa)
}

final class ApplicativeErrorIdOps[E](e: E) {
def raiseError[F[_], A](implicit F: ApplicativeError[F, E]): F[A] =
F.raiseError(e)
}

final class ApplicativeErrorOps[F[_], E, A](fa: F[A])(implicit F: ApplicativeError[F, E]) {
def handleError(f: E => A): F[A] =
F.handleError(fa)(f)

def handleErrorWith(f: E => F[A]): F[A] =
F.handleErrorWith(fa)(f)

def attempt: F[E Xor A] =
F.attempt(fa)

def attemptT: XorT[F, E, A] =
F.attemptT(fa)

def recover(pf: PartialFunction[E, A]): F[A] =
F.recover(fa)(pf)

def recoverWith(pf: PartialFunction[E, F[A]]): F[A] =
F.recoverWith(fa)(pf)
}
1 change: 1 addition & 0 deletions core/src/main/scala/cats/syntax/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cats
package object syntax {
object all extends AllSyntax
object applicative extends ApplicativeSyntax
object applicativeError extends ApplicativeErrorSyntax
object apply extends ApplySyntax
object bifunctor extends BifunctorSyntax
object bifoldable extends BifoldableSyntax
Expand Down
41 changes: 41 additions & 0 deletions tests/src/test/scala/cats/tests/ApplicativeErrorTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package cats
package tests

import cats.data.{Xor, XorT}

class ApplicativeErrorCheck extends CatsSuite {

type ErrorOr[A] = String Xor A

val failed: String Xor Int =
"Badness".raiseError[ErrorOr, Int]

test("raiseError syntax creates an Xor with the correct type parameters") {
failed should === ("Badness".left[Int])
}

test("handleError syntax transforms an error to a success") {
failed.handleError(error => error.length) should === (7.right)
}

test("handleErrorWith transforms an error to a success") {
failed.handleErrorWith(error => error.length.right) should === (7.right)
}

test("attempt syntax creates a wrapped Xor") {
failed.attempt should === ("Badness".left.right)
}

test("attemptT syntax creates an XorT") {
failed.attemptT should === (XorT[ErrorOr, String, Int](failed.right))
}

test("recover syntax transforms an error to a success") {
failed.recover { case error => error.length } should === (7.right)
}

test("recoverWith transforms an error to a success") {
failed.recoverWith { case error => error.length.right } should === (7.right)
}

}
25 changes: 25 additions & 0 deletions tests/src/test/scala/cats/tests/SyntaxTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,29 @@ class SyntaxTests extends AllInstances with AllSyntax {
val la = mock[Eval[A]]
val lfa = la.pureEval[F]
}

def testApplicativeError[F[_, _], E, A](implicit F: ApplicativeError[F[E, ?], E]): Unit = {
type G[X] = F[E, X]

val e = mock[E]
val ga = e.raiseError[G, A]

val gea = mock[G[A]]

val ea = mock[E => A]
val gea1 = ga.handleError(ea)

val egea = mock[E => G[A]]
val gea2 = ga.handleErrorWith(egea)

val gxea = ga.attempt

val gxtea = ga.attemptT

val pfea = mock[PartialFunction[E, A]]
val gea3 = ga.recover(pfea)

val pfegea = mock[PartialFunction[E, G[A]]]
val gea4 = ga.recoverWith(pfegea)
}
}

0 comments on commit 79d40a9

Please sign in to comment.