Repository: rcardin/raise4s (scala)

Issue:
Add a method to lift a value to Raise context
Add a method to lift a value of type `E` to the `Raise[E] ?=> T` context.
The method should look something like the following:

```scala 3
case object Error
def raiseFun: String raises Error = Error.raise[String]
```

Pull request:
Close #4.

Patch:
diff --git a/README.md b/README.md
index e32ff81..ca0ffe2 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,26 @@ The above code will not compile with the following error:
 [error] one error found
 ```
 
+It's also possible to lift a value to the context `Raise[E] ?=> A`. If we want to lift a value of type `A` to the context `Raise[Nothing]`, we can use the `succeed` function:
+
+```scala 3
+def aliceUser: User raises UserNotFound = Raise.succeed(User("42", "Alice"))
+```
+
+More useful is to lift a value of type `E` as the error in the context `Raise[E]`:
+
+```scala 3
+def userNotFound: User raises UserNotFound = UserNotFound("42").raise[User]
+```
+
+We can always rewrite che last function as follows:
+
+```scala 3
+def userNotFound: User raises UserNotFound = {
+  Raise.raise(UserNotFound("42"))
+}
+```
+
 We may have noticed that one advantage of using the `Raise[E]` context is that the return type of the function listed only the happy path. As we’ll see in a moment, this is a huge advantage when we want to compose functions that can raise errors.
 
 As you might guess from the previous compiler error, the Raise DSL is using implicit resolutions under the hood. In fact, to execute a function that uses the Raise DSL we need to provide an instance of the `Raise[E]` type class for the error type `E`. The most generic way to execute a function that can raise an error of type `E` and that is defined in the context of a `Raise[E]` is the `fold` function:
diff --git a/src/main/scala/in/rcard/raise4s/Builders.scala b/src/main/scala/in/rcard/raise4s/Builders.scala
index 7e3854a..6765649 100644
--- a/src/main/scala/in/rcard/raise4s/Builders.scala
+++ b/src/main/scala/in/rcard/raise4s/Builders.scala
@@ -40,3 +40,9 @@ def $try[A](block: Raise[Throwable] ?=> A): Try[A] =
     Failure(_),
     Success(_)
   )
+
+object RaiseAnyPredef:
+  extension [A](value: A) def succeed: Raise[Nothing] ?=> A = { value }
+
+  extension [Error](value: Error)(using raise: Raise[Error])
+    def raise[A]: Raise[Error] ?=> A = raise.raise(value)


Test patch:
diff --git a/src/test/scala/in/rcard/raise4s/BuildersSpec.scala b/src/test/scala/in/rcard/raise4s/BuildersSpec.scala
index b734cfd..3351b0b 100644
--- a/src/test/scala/in/rcard/raise4s/BuildersSpec.scala
+++ b/src/test/scala/in/rcard/raise4s/BuildersSpec.scala
@@ -1,5 +1,6 @@
 package in.rcard.raise4s
 
+import in.rcard.raise4s.RaiseAnyPredef.{succeed, raise}
 import in.rcard.raise4s.RaiseEitherPredef.bind
 import in.rcard.raise4s.RaiseOptionPredef.bind
 import in.rcard.raise4s.RaiseTryPredef.bind
@@ -82,4 +83,31 @@ class BuildersSpec extends AnyFlatSpec with Matchers {
 
     actual should be(Success(2))
   }
+
+  "The succeed extension method" should "lift a value in the raise context" in {
+    Raise.fold(
+      42.succeed,
+      identity,
+      _ => "meaning of life"
+    ) should be("meaning of life")
+  }
+
+  it should "be composable with any other raising lambda" in {
+    Raise.fold(
+      {
+        val meaningOfLife: Int = 42.succeed
+        Raise.raise("error")
+      },
+      identity,
+      _ => "success"
+    ) should be("error")
+  }
+
+  "The raise builder" should "raise an error using the extension receiver value" in {
+    Raise.fold(
+      "error".raise[Int],
+      identity,
+      _ => "42"
+    ) should be("error")
+  }
 }