Skip to content

Commit

Permalink
Added builders 'validated', 'validatedNec', and 'validatedNel'
Browse files Browse the repository at this point in the history
  • Loading branch information
rcardin committed Jun 28, 2024
1 parent ef98c2f commit 1d11628
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 3 deletions.
8 changes: 7 additions & 1 deletion cats-raise4s/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,10 @@ In general, the integration lets you use the _Cats_ type classes with the _Raise
val one: Validated[String, Int] = Validated.Valid(1)
val actual: Int = Raise.recover(one.value) { _ => 2 }
actual should be(1)
```
```

- Convert a `A raises Error` block into a `Validated[Error, A]` instance. The library has also builders `validatedNec` and `validatedNel` to convert into `ValidatedNec` and `ValidatedNel` instances.

```scala 3
CatsRaise.validated { raise("error") } should be(Validated. invalid("error"))
```
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package in.rcard.raise4s.cats

import cats.Semigroup
import cats.data.NonEmptyList
import cats.data.*
import in.rcard.raise4s.Raise

object CatsRaise {
Expand Down Expand Up @@ -1394,4 +1394,77 @@ object CatsRaise {
block(a, b)
}
}

/** Runs a computation `block` using [[Raise]], and return its outcome as [[Validated]].
* - [[Validated.Valid]] represents success,
* - [[Validated.Invalid]] represents logical failure.
*
* This function re-throws any exceptions thrown within the [[Raise]] block.
*
* <h2>Example</h2>
* {{{
* CatsRaise.validated { raise("error") } should be(Validated.invalid("error"))
* }}}
*
* @param block
* A computation that can raise errors of type `Error`
* @tparam A
* The type of the value returned by the computation
* @tparam Error
* The type of the logical error that can be raised by the computation
* @return
* An [[Validated]] representing the outcome of the computation
*/
inline def validated[Error, A](inline block: Raise[Error] ?=> A): Validated[Error, A] =
Raise.fold(
block,
error => Validated.invalid(error),
value => Validated.valid(value)
)

/** Runs a computation `block` using [[Raise]], and return its outcome as [[ValidatedNec]].
*
* <h2>Example</h2>
* {{{
* CatsRaise.validatedNec {
* raise("error")
* } should be(Validated.invalid(NonEmptyChain.one("error")))
* }}}
*
* @param block
* A computation that can raise errors of type `Error`
* @tparam A
* The type of the value returned by the computation
* @tparam Error
* The type of the logical error that can be raised by the computation
* @return
* An [[ValidatedNec]] representing the outcome of the computation
*/
inline def validatedNec[Error, A](inline block: Raise[Error] ?=> A): ValidatedNec[Error, A] =
validated(
Raise.withError[NonEmptyChain[Error], Error, A](error => NonEmptyChain.one(error))(block)
)

/** Runs a computation `block` using [[Raise]], and return its outcome as [[ValidatedNel]].
*
* <h2>Example</h2>
* {{{
* CatsRaise.validatedNel {
* raise("error")
* } should be(Validated.invalid(NonEmptyList.one("error")))
* }}}
*
* @param block
* A computation that can raise errors of type `Error`
* @tparam A
* The type of the value returned by the computation
* @tparam Error
* The type of the logical error that can be raised by the computation
* @return
* An [[ValidatedNel]] representing the outcome of the computation
*/
inline def validatedNel[Error, A](inline block: Raise[Error] ?=> A): ValidatedNel[Error, A] =
validated(
Raise.withError[NonEmptyList[Error], Error, A](error => NonEmptyList.one(error))(block)
)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package in.rcard.raise4s.cats

import cats.Semigroup
import cats.data.NonEmptyList
import cats.data.{NonEmptyChain, NonEmptyList, Validated}
import in.rcard.raise4s.RaiseAnyPredef.raise
import in.rcard.raise4s.{Raise, raises}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
Expand Down Expand Up @@ -169,4 +170,36 @@ class CatsRaiseSpec extends AnyFlatSpec with Matchers {

actual shouldBe NonEmptyList.of("2", "4", "6", "8")
}

"The 'validated' builder" should "create a Valid instance" in {
CatsRaise.validated({ 42 }) should be(Validated.valid(42))
}

it should "create an Invalid instance" in {
CatsRaise.validated { raise("error") } should be(Validated.invalid("error"))
}

"The 'validatedNec' builder" should "create a Valid instance" in {
CatsRaise.validatedNec {
42
} should be(Validated.valid(42))
}

it should "create an Invalid instance" in {
CatsRaise.validatedNec {
raise("error")
} should be(Validated.invalid(NonEmptyChain.one("error")))
}

"The 'validatedNel' builder" should "create a Valid instance" in {
CatsRaise.validatedNel {
42
} should be(Validated.valid(42))
}

it should "create an Invalid instance" in {
CatsRaise.validatedNel {
raise("error")
} should be(Validated.invalid(NonEmptyList.one("error")))
}
}

0 comments on commit 1d11628

Please sign in to comment.