forked from effekt-lang/effekt
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Examples / Unit Tests for Exceptions (effekt-lang#775)
## Motivation Resolves effekt-lang#480 This module demonstrates exception handling combinators in Effekt using a simple, focused example. By showcasing custom exception handling (`TestException`) with different strategies (default handling, ignoring, reporting, finalizing), it provides a practical guide for understanding these features. ## Changes - Introduced `TestException` as a custom exception type, independent of other exceptions like `OutOfBounds`. - Added `generalOperation`, which raises a `TestException` for invalid input or returns a string. - Included tests for handling exceptions with: - Default behavior - Ignoring exceptions - Reporting exceptions - Finalization hooks - "Reifying" with Results ## Testing The examples are self-contained in the `main` function, covering all provided exception-handling strategies. Each approach is tested and outputs expected results for validation (`combinators.check`).
- Loading branch information
1 parent
061473a
commit cbc3e8c
Showing
2 changed files
with
84 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
Test: Default Handling | ||
hello | ||
hello | ||
Error: Invalid index (0) | ||
Error: Invalid index (-1) | ||
hello | ||
Test: Finalizer | ||
hello | ||
Test: Finalizer | ||
Error: Invalid index (0) | ||
Success: hello |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
module examples/pos/exception/combinators | ||
|
||
import exception | ||
import result | ||
|
||
|
||
/// Used as a type for `Exception` purely for independent testing | ||
record TestException() | ||
|
||
|
||
/// Returns the string if index > 0; otherwise raises a TestException. | ||
def generalOperation(str: String, index: Int): String / Exception[TestException] = { | ||
if (index <= 0) | ||
do raise(TestException(), "Error: Invalid index (" ++ show(index) ++ ")") | ||
else | ||
str | ||
} | ||
|
||
def main() = { | ||
val str: String = "hello" | ||
|
||
// Test for default handling of TestException | ||
def defaultTestException { p: => String / Exception[TestException] }: Unit = { | ||
with on[TestException].default { println("Test: Default Handling") } | ||
println(p().show) | ||
} | ||
|
||
defaultTestException { str.generalOperation(0) } // Test: Default Handling | ||
defaultTestException { str.generalOperation(1) } // hello | ||
|
||
// Test for ignoring TestException | ||
def ignoreTestException { p: => String / Exception[TestException] }: Unit = { | ||
with on[TestException].ignore(); | ||
println(p().show) | ||
} | ||
|
||
ignoreTestException { str.generalOperation(0) } // *ignores the TestException* | ||
ignoreTestException { str.generalOperation(1) } // hello | ||
|
||
// Test for reporting TestException | ||
def reportTestException { p: => String / Exception[TestException] }: Unit = { | ||
with on[TestException].report(); | ||
println(p().show) | ||
} | ||
|
||
reportTestException { str.generalOperation(0) } // Error: Invalid index (0) | ||
reportTestException { str.generalOperation(-1) }// Error: Invalid index (-1) | ||
reportTestException { str.generalOperation(1) } // hello | ||
|
||
// Test for finalizing TestException | ||
def finalizeTestException { p: => String / Exception[TestException] }: Unit = { | ||
try { | ||
with on[TestException].finalize { println("Test: Finalizer") } | ||
println(p().show) | ||
} with Exception[TestException] { def raise(exception, msg) = () } | ||
} | ||
|
||
finalizeTestException { str.generalOperation(0) } // Test: Finalizer | ||
finalizeTestException { str.generalOperation(1) } // Test: Finalizer hello | ||
|
||
// Test for "reifying" an Exception using Result | ||
def resultTestException { p: => String / Exception[TestException] }: Unit = { | ||
val res = result[String, TestException] { p() } | ||
res match { | ||
case Success(msg) => println("Success: " ++ msg) | ||
case Error(exc, msg) => println(msg) | ||
} | ||
} | ||
|
||
resultTestException { str.generalOperation(0) } // Error: Invalid index (0) | ||
resultTestException { str.generalOperation(1) } // Success: hello | ||
|
||
} |