Repository: rcardin/raise4s (scala)

Issue:
Add an extension method on the family of `Validated` types to convert them to a `Raise`
Add an extension method on the family of `Validated` types to convert them to a `Raise`.

The types to convert are:
- `Validated`
- `ValidatedNel`
- `ValidatedNec`

The method should be called `value`, as for the other conversion functions.

Pull request:
Closes #60

Patch:
diff --git a/cats-raise4s/README.md b/cats-raise4s/README.md
index 2e15bbb..391dc6b 100644
--- a/cats-raise4s/README.md
+++ b/cats-raise4s/README.md
@@ -96,4 +96,12 @@ In general, the integration lets you use the _Cats_ type classes with the _Raise
     identity
   )
   actual should be(List(1, 2))
-  ```
\ No newline at end of file
+  ```
+
+- Convert a `Validated[Error, A]` instance to a `A raises Error` instance (it works with `ValidatedNel` and `ValidatedNec` either).
+
+  ```scala 3
+  val one: Validated[String, Int] = Validated.Valid(1)
+  val actual: Int = Raise.recover(one.value) { _ => 2 }
+  actual should be(1)
+  ``` 
\ No newline at end of file
diff --git a/cats-raise4s/src/main/scala/in/rcard/raise4s/cats/CatsBind.scala b/cats-raise4s/src/main/scala/in/rcard/raise4s/cats/CatsBind.scala
new file mode 100644
index 0000000..3f27a84
--- /dev/null
+++ b/cats-raise4s/src/main/scala/in/rcard/raise4s/cats/CatsBind.scala
@@ -0,0 +1,13 @@
+package in.rcard.raise4s.cats
+
+import cats.data.Validated
+import cats.data.Validated.{Invalid, Valid}
+import in.rcard.raise4s.Raise
+
+object CatsBind {
+  extension [Error, A](validated: Validated[Error, A])
+    inline def value(using Raise[Error]): A = validated match {
+      case Valid(value)   => value
+      case Invalid(error) => Raise.raise(error)
+    }
+}


Test patch:
diff --git a/cats-raise4s/src/test/scala/in/rcard/raise4s/cats/CatsBindSpec.scala b/cats-raise4s/src/test/scala/in/rcard/raise4s/cats/CatsBindSpec.scala
new file mode 100644
index 0000000..a0a4d01
--- /dev/null
+++ b/cats-raise4s/src/test/scala/in/rcard/raise4s/cats/CatsBindSpec.scala
@@ -0,0 +1,46 @@
+package in.rcard.raise4s.cats
+
+import cats.data.*
+import in.rcard.raise4s.Raise
+import in.rcard.raise4s.cats.CatsBind.value
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+class CatsBindSpec extends AnyFlatSpec with Matchers {
+
+  "Validated.value" should "return the value if it's valid" in {
+
+    val one: Validated[String, Int] = Validated.Valid(1)
+
+    val actual: Int = Raise.recover(one.value) { _ => 2 }
+
+    actual should be(1)
+  }
+
+  it should "raise an error if it's invalid" in {
+
+    val invalid: Validated[String, Int] = Validated.Invalid("error")
+
+    val actual: Int = Raise.recover(invalid.value) { err => if (err == "error") 2 else 3 }
+
+    actual should be(2)
+  }
+
+  it should "work with invalid ValidatedNel" in {
+
+    val invalid: ValidatedNel[String, Int] = Validated.invalid(NonEmptyList.one("error"))
+
+    val actual: Int = Raise.recover(invalid.value) { err => if (err.head == "error") 2 else 3 }
+
+    actual should be(2)
+  }
+
+  it should "work with invalid ValidatedNec" in {
+
+    val invalid: ValidatedNec[String, Int] = Validated.invalid(NonEmptyChain.one("error"))
+
+    val actual: Int = Raise.recover(invalid.value) { err => if (err.head == "error") 2 else 3 }
+
+    actual should be(2)
+  }
+}