Skip to main content

fp_library/
brands.rs

1//! Brands represent higher-kinded (unapplied/partially-applied) forms of
2//! [types][crate::types], as opposed to concrete types, which are
3//! fully-applied.
4//!
5//! For example, [`VecBrand`] represents the higher-kinded type [`Vec`], whereas
6//! `Vec A`/`Vec<A>` is the concrete type where `Vec` has been applied to some
7//! generic type `A`.
8//!
9//! ### Examples
10//!
11//! ```
12//! use fp_library::{
13//! 	brands::*,
14//! 	functions::*,
15//! };
16//!
17//! let x = Some(5);
18//! let y = map::<OptionBrand, _, _>(|i| i * 2, x);
19//! assert_eq!(y, Some(10));
20//! ```
21
22use {
23	crate::classes::RefCountedPointer,
24	std::marker::PhantomData,
25};
26
27pub mod optics;
28
29/// Brand for [`Arc`](std::sync::Arc) atomic reference-counted pointer.
30#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
31pub struct ArcBrand;
32
33/// Brand for [atomically reference-counted][std::sync::Arc]
34/// [closures][Fn] (`Arc<dyn Fn(A) -> B>`).
35///
36/// This type alias provides a way to construct and type-check [`Arc`](std::sync::Arc)-wrapped
37/// closures in a generic context.
38pub type ArcFnBrand = FnBrand<ArcBrand>;
39
40/// An adapter that partially applies a `Bifunctor` to its first argument, creating a `Functor` over the second argument.
41///
42/// ### Examples
43///
44/// ```
45/// use fp_library::{
46/// 	brands::*,
47/// 	classes::functor::map,
48/// };
49///
50/// let x = Result::<i32, i32>::Ok(5);
51/// let y = map::<BifunctorFirstAppliedBrand<ResultBrand, i32>, _, _>(|s| s * 2, x);
52/// assert_eq!(y, Ok(10));
53/// ```
54#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
55pub struct BifunctorFirstAppliedBrand<Brand, A>(PhantomData<(Brand, A)>);
56
57/// An adapter that partially applies a `Bifunctor` to its second argument, creating a `Functor` over the first argument.
58///
59/// ### Examples
60///
61/// ```
62/// use fp_library::{
63/// 	brands::*,
64/// 	classes::functor::map,
65/// };
66///
67/// let x = Result::<i32, i32>::Err(5);
68/// let y = map::<BifunctorSecondAppliedBrand<ResultBrand, i32>, _, _>(|e| e * 2, x);
69/// assert_eq!(y, Err(10));
70/// ```
71#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
72pub struct BifunctorSecondAppliedBrand<Brand, B>(PhantomData<(Brand, B)>);
73
74/// Brand for [`CatList`](crate::types::CatList).
75#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
76pub struct CatListBrand;
77
78/// Generic function brand parameterized by reference-counted pointer choice.
79#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
80pub struct FnBrand<PtrBrand: RefCountedPointer>(PhantomData<PtrBrand>);
81
82/// Brand for [`Identity`](crate::types::Identity).
83#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
84pub struct IdentityBrand;
85
86/// Brand for [`Lazy`](crate::types::Lazy).
87#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
88pub struct LazyBrand<Config>(PhantomData<Config>);
89
90/// Brand for [`Option`].
91#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
92pub struct OptionBrand;
93
94/// Brand for [`Pair`](crate::types::Pair).
95#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
96pub struct PairBrand;
97
98/// Brand for the partially-applied form of [`Pair`](crate::types::Pair) with the first value applied.
99#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
100pub struct PairFirstAppliedBrand<First>(PhantomData<First>);
101
102/// Brand for the partially-applied form of [`Pair`](crate::types::Pair) with the second value applied.
103#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
104pub struct PairSecondAppliedBrand<Second>(PhantomData<Second>);
105
106/// An adapter that partially applies a `Profunctor` to its first argument, creating a `Functor`.
107///
108/// ### Examples
109///
110/// ```
111/// use fp_library::{
112/// 	brands::*,
113/// 	classes::functor::map,
114/// };
115///
116/// let f = |x: i32| x + 1;
117/// let g = map::<ProfunctorFirstAppliedBrand<RcFnBrand, i32>, _, _>(
118/// 	|y: i32| y * 2,
119/// 	std::rc::Rc::new(f) as std::rc::Rc<dyn Fn(i32) -> i32>,
120/// );
121/// assert_eq!(g(10), 22); // (10 + 1) * 2 = 22
122/// ```
123#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
124pub struct ProfunctorFirstAppliedBrand<Brand, A>(PhantomData<(Brand, A)>);
125
126/// An adapter that partially applies a `Profunctor` to its second argument, creating a `Contravariant` functor.
127///
128/// ### Examples
129///
130/// ```
131/// use fp_library::{
132/// 	brands::*,
133/// 	classes::contravariant::contramap,
134/// };
135///
136/// let f = |x: i32| x > 5;
137/// let is_long_int = contramap::<ProfunctorSecondAppliedBrand<RcFnBrand, bool>, _, _>(
138/// 	|s: String| s.len() as i32,
139/// 	std::rc::Rc::new(f) as std::rc::Rc<dyn Fn(i32) -> bool>,
140/// );
141/// assert_eq!(is_long_int("123456".to_string()), true);
142/// assert_eq!(is_long_int("123".to_string()), false);
143/// ```
144#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
145pub struct ProfunctorSecondAppliedBrand<Brand, B>(PhantomData<(Brand, B)>);
146
147/// Brand for [`Rc`](`std::rc::Rc`) reference-counted pointer.
148#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
149pub struct RcBrand;
150
151/// Brand for [reference-counted][std::rc::Rc] [closures][Fn]
152/// (`Rc<dyn Fn(A) -> B>`).
153///
154/// This type alias provides a way to construct and type-check [`Rc`](`std::rc::Rc`)-wrapped
155/// closures in a generic context.
156pub type RcFnBrand = FnBrand<RcBrand>;
157
158/// Brand for [`Result`].
159#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
160pub struct ResultBrand;
161
162/// Brand for the partially-applied form of [`Result`] with the [`Err`] type applied.
163///
164/// This brand forms a [`crate::classes::Functor`] and [`crate::classes::Monad`] over the success ([`Ok`]) type.
165#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
166pub struct ResultErrAppliedBrand<E>(PhantomData<E>);
167
168/// Brand for the partially-applied form of [`Result`] with the [`Ok`] type applied.
169///
170/// This brand forms a [`crate::classes::Functor`] and [`crate::classes::Monad`] over the error ([`Err`]) type.
171#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
172pub struct ResultOkAppliedBrand<T>(PhantomData<T>);
173
174/// Brand for [`Step`](crate::types::Step).
175#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
176pub struct StepBrand;
177
178/// Brand for the partially-applied form of [`Step`](crate::types::Step) with the [`Done`](crate::types::Step::Done) type applied.
179#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
180pub struct StepDoneAppliedBrand<B>(PhantomData<B>);
181
182/// Brand for the partially-applied form of [`Step`](crate::types::Step) with the [`Loop`](crate::types::Step::Loop) type applied.
183#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
184pub struct StepLoopAppliedBrand<A>(PhantomData<A>);
185
186/// Brand for [`Thunk`](crate::types::Thunk).
187///
188/// Note: This is for `Thunk<'a, A>`, NOT for `Trampoline<A>`.
189/// `Trampoline` cannot implement HKT traits due to its `'static` requirement.
190#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
191pub struct ThunkBrand;
192
193/// Brand for [`TryLazy`](crate::types::TryLazy).
194#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
195pub struct TryLazyBrand<E, Config>(PhantomData<(E, Config)>);
196
197/// Brand for [`TryThunk`](crate::types::TryThunk) (Bifunctor).
198#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
199pub struct TryThunkBrand;
200
201/// Brand for [`TryThunk`](crate::types::TryThunk) with the error value applied (Functor over [`Ok`]).
202#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
203pub struct TryThunkErrAppliedBrand<E>(PhantomData<E>);
204
205/// Brand for [`TryThunk`](crate::types::TryThunk) with the success value applied (Functor over [`Err`]).
206#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
207pub struct TryThunkOkAppliedBrand<A>(PhantomData<A>);
208
209/// Brand for `(A,)`, with A not applied.
210#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
211pub struct Tuple1Brand;
212
213/// Brand for `(First, Second)`, with neither `First` nor `Second` applied.
214#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
215pub struct Tuple2Brand;
216
217/// Brand for `(First, Second)`, with `First` applied (Functor over `Second`).
218#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
219pub struct Tuple2FirstAppliedBrand<First>(PhantomData<First>);
220
221/// Brand for `(First, Second)`, with `Second` applied (Functor over `First`).
222#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
223pub struct Tuple2SecondAppliedBrand<Second>(PhantomData<Second>);
224
225/// Brand for [`Vec`].
226#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
227pub struct VecBrand;