fp_library/typeclasses/functor.rs
1use crate::{
2 aliases::ArcFn,
3 hkt::{Apply1, Kind1},
4};
5
6/// A typeclass for types that can be mapped over.
7///
8/// A `Functor` represents a context or container that allows functions to be applied
9/// to values within that context without altering the structure of the context itself.
10///
11/// # Laws
12///
13/// Functors must satisfy the following laws:
14/// * Identity: `map(identity) = identity`.
15/// * Composition: `map(f . g) = map(f) . map(g)`.
16pub trait Functor: Kind1 {
17 /// Maps a function over the values in the functor context.
18 ///
19 /// # Type Signature
20 ///
21 /// `forall f a b. Functor f => (a -> b) -> f a -> f b`
22 ///
23 /// # Parameters
24 ///
25 /// * `f`: A function to apply to the values within the functor context.
26 /// * `fa`: A functor containing values of type `A`.
27 ///
28 /// # Returns
29 ///
30 /// A functor containing values of type `B`.
31 fn map<'a, A: 'a, B: 'a>(f: ArcFn<'a, A, B>) -> ArcFn<'a, Apply1<Self, A>, Apply1<Self, B>>;
32}
33
34/// Maps a function over the values in the functor context.
35///
36/// Free function version that dispatches to [the typeclass' associated function][`Functor::map`].
37///
38/// # Type Signature
39///
40/// `forall f a b. Functor f => (a -> b) -> f a -> f b`
41///
42/// # Parameters
43///
44/// * `f`: A function to apply to the values within the functor context.
45/// * `fa`: A functor containing values of type `A`.
46///
47/// # Returns
48///
49/// A functor containing values of type `B`.
50///
51/// # Examples
52///
53/// ```
54/// use fp_library::{brands::OptionBrand, functions::map};
55/// use std::sync::Arc;
56///
57/// assert_eq!(map::<OptionBrand, _, _>(Arc::new(|x: i32| x * 2))(Some(5)), Some(10));
58/// ```
59pub fn map<'a, Brand: Functor + ?Sized, A: 'a, B: 'a>(
60 f: ArcFn<'a, A, B>
61) -> ArcFn<'a, Apply1<Brand, A>, Apply1<Brand, B>> {
62 Brand::map(f)
63}