error_rail/traits/
error_category.rs

1use crate::traits::*;
2
3/// Trait for types that can lift values and handle errors in a functorial way.
4///
5/// This trait provides a categorical abstraction over error-handling types,
6/// allowing them to:
7/// - Lift pure values into the error context (`lift`)
8/// - Construct error cases from error values (`handle_error`)
9///
10/// # Type Parameters
11///
12/// * `E` - The error type that this category handles
13///
14/// # Associated Types
15///
16/// * `ErrorFunctor<T>` - The functor type that wraps values of type `T` with error handling
17///
18/// # Examples
19///
20/// ```
21/// use error_rail::traits::ErrorCategory;
22///
23/// let success: Result<i32, &str> = <Result<(), &str>>::lift(42);
24/// assert_eq!(success, Ok(42));
25///
26/// let failure: Result<i32, &str> = <Result<(), &str>>::handle_error("error");
27/// assert_eq!(failure, Err("error"));
28/// ```
29pub trait ErrorCategory<E> {
30    /// The functor type that wraps values with error handling capability.
31    type ErrorFunctor<T>: WithError<E>;
32
33    /// Lifts a pure value into the error functor context.
34    ///
35    /// # Arguments
36    ///
37    /// * `value` - The value to lift into the error context
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use error_rail::traits::ErrorCategory;
43    ///
44    /// let result: Result<i32, &str> = <Result<(), &str>>::lift(42);
45    /// assert_eq!(result, Ok(42));
46    /// ```
47    fn lift<T>(value: T) -> Self::ErrorFunctor<T>;
48
49    /// Constructs an error case from an error value.
50    ///
51    /// # Arguments
52    ///
53    /// * `error` - The error value to wrap
54    ///
55    /// # Examples
56    ///
57    /// ```
58    /// use error_rail::traits::ErrorCategory;
59    ///
60    /// let result: Result<i32, &str> = <Result<(), &str>>::handle_error("failed");
61    /// assert_eq!(result, Err("failed"));
62    /// ```
63    fn handle_error<T>(error: E) -> Self::ErrorFunctor<T>;
64}
65
66/// Implementation of `ErrorCategory` for `Result` types.
67///
68/// This allows `Result<(), E>` to act as an error category, where:
69/// - `lift` creates `Ok` values
70/// - `handle_error` creates `Err` values
71///
72/// # Examples
73///
74/// ```
75/// use error_rail::traits::ErrorCategory;
76///
77/// let ok_value: Result<i32, String> = <Result<(), String>>::lift(100);
78/// assert_eq!(ok_value, Ok(100));
79///
80/// let err_value: Result<i32, String> = <Result<(), String>>::handle_error("error".to_string());
81/// assert_eq!(err_value, Err("error".to_string()));
82/// ```
83impl<E: Clone> ErrorCategory<E> for Result<(), E> {
84    type ErrorFunctor<T> = Result<T, E>;
85
86    #[inline]
87    fn lift<T>(value: T) -> Result<T, E> {
88        Ok(value)
89    }
90
91    #[inline]
92    fn handle_error<T>(error: E) -> Result<T, E> {
93        Err(error)
94    }
95}