fp_library/classes/evaluable.rs
1//! Functors whose effects can be evaluated to produce an inner value.
2//!
3//! This trait is used by [`Free::evaluate`](crate::types::Free::evaluate) to execute the effects
4//! in a [`Free`](crate::types::Free) monad.
5//!
6//! ### Examples
7//!
8//! ```
9//! use fp_library::{brands::*, functions::*, types::*};
10//!
11//! let thunk = Thunk::new(|| 42);
12//! assert_eq!(evaluate::<ThunkBrand, _>(thunk), 42);
13//! ```
14
15use crate::{Apply, classes::functor::Functor, kinds::*};
16use fp_macros::doc_params;
17use fp_macros::doc_type_params;
18use fp_macros::hm_signature;
19
20/// A functor whose effects can be evaluated to produce the inner value.
21///
22/// This trait is used by [`Free::evaluate`](crate::types::Free::evaluate) to execute the effects
23/// in a [`Free`](crate::types::Free) monad.
24pub trait Evaluable: Functor {
25 /// Evaluates the effect, producing the inner value.
26 ///
27 /// ### Type Signature
28 ///
29 #[hm_signature(Evaluable)]
30 ///
31 /// ### Type Parameters
32 ///
33 #[doc_type_params("The lifetime of the value.", "The type of the value inside the functor.")]
34 ///
35 /// ### Parameters
36 ///
37 #[doc_params("The functor instance to evaluate.")]
38 ///
39 /// ### Returns
40 ///
41 /// The inner value.
42 ///
43 /// ### Examples
44 ///
45 /// ```
46 /// use fp_library::{brands::*, functions::*, types::*};
47 ///
48 /// let eval = Thunk::new(|| 42);
49 /// assert_eq!(evaluate::<ThunkBrand, _>(eval), 42);
50 /// ```
51 fn evaluate<'a, A: 'a>(fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)) -> A;
52}
53
54/// Evaluates the effect, producing the inner value.
55///
56/// Free function version that dispatches to [the type class' associated function][`Evaluable::evaluate`].
57///
58/// ### Type Signature
59///
60#[hm_signature(Evaluable)]
61///
62/// ### Type Parameters
63///
64#[doc_type_params(
65 "The lifetime of the value.",
66 "The evaluable functor.",
67 "The type of the value inside the functor."
68)]
69///
70/// ### Parameters
71///
72#[doc_params("The functor instance to evaluable.")]
73///
74/// ### Returns
75///
76/// The inner value.
77///
78/// ### Examples
79///
80/// ```
81/// use fp_library::{brands::*, functions::*, types::*};
82///
83/// let eval = Thunk::new(|| 42);
84/// assert_eq!(evaluate::<ThunkBrand, _>(eval), 42);
85/// ```
86pub fn evaluate<'a, F, A>(fa: Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)) -> A
87where
88 F: Evaluable,
89 A: 'a,
90{
91 F::evaluate(fa)
92}