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