fp_library/classes/try_semigroup.rs
1//! A trait for types that can be combined fallibly.
2//!
3//! This is similar to `Semigroup`, but the combination operation returns a `Result`.
4//! This is useful for types like `Lazy` where combination might trigger evaluation
5//! that could fail (panic).
6//!
7//! ### Examples
8//!
9//! ```
10//! use fp_library::{brands::*, classes::*, functions::*};
11//!
12//! let x = String::from("Hello, ");
13//! let y = String::from("World!");
14//! let z = try_append(x, y);
15//! assert_eq!(z, Ok(String::from("Hello, World!")));
16//! ```
17
18use super::Semigroup;
19
20/// A trait for types that can be combined fallibly.
21///
22/// This is similar to [`Semigroup`], but the combination operation returns a `Result`.
23/// This is useful for types like `Lazy` where combination might trigger evaluation
24/// that could fail (panic).
25pub trait TrySemigroup: Sized {
26 /// The error type that can occur during combination.
27 type Error;
28
29 /// Fallibly combine two values.
30 ///
31 /// ### Type Signature
32 ///
33 /// `forall a. TrySemigroup a => (a, a) -> Result a a::Error`
34 ///
35 /// ### Parameters
36 ///
37 /// * `x`: The first value to combine.
38 /// * `y`: The second value to combine.
39 ///
40 /// ### Returns
41 ///
42 /// The result of combining `x` and `y`, or an error.
43 ///
44 /// ### Examples
45 ///
46 /// ```
47 /// use fp_library::{brands::*, classes::*, functions::*};
48 ///
49 /// let x = String::from("Hello, ");
50 /// let y = String::from("World!");
51 /// let z = String::try_append(x, y);
52 /// assert_eq!(z, Ok(String::from("Hello, World!")));
53 /// ```
54 fn try_append(
55 x: Self,
56 y: Self,
57 ) -> Result<Self, Self::Error>;
58}
59
60impl<T: Semigroup> TrySemigroup for T {
61 type Error = std::convert::Infallible;
62
63 fn try_append(
64 x: Self,
65 y: Self,
66 ) -> Result<Self, Self::Error> {
67 Ok(<T as Semigroup>::append(x, y))
68 }
69}
70
71/// Fallibly combine two values.
72///
73/// Free function version that dispatches to [the type class' associated function][`TrySemigroup::try_append`].
74///
75/// ### Type Signature
76///
77/// `forall a. TrySemigroup a => (a, a) -> Result a a::Error`
78///
79/// ### Type Parameters
80///
81/// * `A`: The type of the values to combine.
82///
83/// ### Parameters
84///
85/// * `x`: The first value to combine.
86/// * `y`: The second value to combine.
87///
88/// ### Returns
89///
90/// The result of combining `x` and `y`, or an error.
91///
92/// ### Examples
93///
94/// ```
95/// use fp_library::{brands::*, classes::*, functions::*};
96///
97/// let x = String::from("Hello, ");
98/// let y = String::from("World!");
99/// let z = try_append(x, y);
100/// assert_eq!(z, Ok(String::from("Hello, World!")));
101/// ```
102pub fn try_append<A: TrySemigroup>(
103 x: A,
104 y: A,
105) -> Result<A, A::Error> {
106 A::try_append(x, y)
107}