diff --git a/README.md b/README.md index 43f0d9e..dbd8005 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,13 @@ val three = Raise.either { The `value` function calls the `raise` function if the `Either` instance is a `Left`; otherwise, it returns the value wrapped by the `Right` instance. Despite the trivial logic implemented in the above example, it's a good example of how to compose functions that return an `Either[E, A]` using the Raise DSL without the use of any `flatMap` function. +A useful shortcut is available when we need to transform a `List[Either[E, A]]` into a `List[A] raises E`. The eventual raised error `E` is the first error found in the list of `Either[E, A]`: + +```scala 3 +val eitherList: List[Either[String, Int]] = List(Right(1), Left("error"), Right(3)) +val raiseList: List[Int] raises String = listWithError.value +``` + Be aware that before version 0.0.5, the `value` function was called `bind()`. We can do the same with `Try[A]` and `Option[A]` using the `asTry` and `option` builders, respectively. Let's start with the `asTry` builder. In this case, the only available type of error is `Throwable`: diff --git a/src/main/scala/in/rcard/raise4s/Bind.scala b/src/main/scala/in/rcard/raise4s/Bind.scala index 8508bb6..07b28e7 100644 --- a/src/main/scala/in/rcard/raise4s/Bind.scala +++ b/src/main/scala/in/rcard/raise4s/Bind.scala @@ -9,6 +9,9 @@ object Bind { case Right(value) => value case Left(error) => Raise.raise(error) } + + extension [Error, A](list: List[Either[Error, A]]) + def value(using Raise[Error]): List[A] = list.map(_.value) extension [A](option: Option[A]) def value(using Raise[None.type]): A = option match { diff --git a/src/test/scala/in/rcard/raise4s/BindTest.scala b/src/test/scala/in/rcard/raise4s/BindTest.scala index 1e66df3..b9cc87b 100644 --- a/src/test/scala/in/rcard/raise4s/BindTest.scala +++ b/src/test/scala/in/rcard/raise4s/BindTest.scala @@ -46,4 +46,17 @@ class BindTest extends AnyFlatSpec with Matchers { actual should be(Success(2)) } + + "List[Either[Error, A]].value" should "return a value if the list doesn't contain errors and raise an error otherwise" in { + val list: List[Either[String, Int]] = List(Right(1), Right(2), Right(3)) + val listWithError: List[Either[String, Int]] = List(Right(1), Left("error"), Right(3)) + + val actual = Raise.either { + val x = list.value + val y = recover({ listWithError.value }) { _ => List(1) } + x.sum + y.sum + } + + actual should be(Right(7)) + } }