fp_library/types/
solo.rs

1//! Implementations for [`Solo`], a type that wraps a value.
2
3use crate::{
4	brands::{Brand, Brand1},
5	functions::{identity, map},
6	hkt::{Apply, Kind, Kind1},
7	typeclasses::{Apply as TypeclassApply, ApplyFirst, ApplySecond, Bind, Functor, Pure},
8};
9
10/// Wraps a value.
11#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
12pub struct Solo<A>(pub A);
13
14/// [Brand][crate::brands] for [`Solo`].
15pub struct SoloBrand;
16
17impl<A> Kind1<A> for SoloBrand {
18	type Output = Solo<A>;
19}
20
21impl<A> Brand1<Solo<A>, A> for SoloBrand {
22	fn inject(a: Solo<A>) -> Apply<Self, (A,)> {
23		a
24	}
25	fn project(a: Apply<Self, (A,)>) -> Solo<A> {
26		a
27	}
28}
29
30impl Pure for SoloBrand {
31	/// # Examples
32	///
33	/// ```
34	/// use fp_library::{brands::SoloBrand, functions::pure, types::Solo};
35	///
36	/// assert_eq!(pure::<SoloBrand, _>(()), Solo(()));
37	/// ```
38	fn pure<A>(a: A) -> Apply<Self, (A,)> {
39		Solo(a)
40	}
41}
42
43impl Functor for SoloBrand {
44	/// # Examples
45	///
46	/// ```
47	/// use fp_library::{brands::SoloBrand, functions::{identity, map}, types::Solo};
48	///
49	/// assert_eq!(map::<SoloBrand, _, _, _>(identity)(Solo(())), Solo(()));
50	/// ```
51	fn map<F, A, B>(f: F) -> impl Fn(Apply<Self, (A,)>) -> Apply<Self, (B,)>
52	where
53		Self: Kind<(A,)> + Kind<(B,)>,
54		F: Fn(A) -> B,
55	{
56		move |fa| <Self as Brand<_, _>>::inject(Solo(f(<Self as Brand<_, _>>::project(fa).0)))
57	}
58}
59
60impl TypeclassApply for SoloBrand {
61	/// # Examples
62	///
63	/// ```
64	/// use fp_library::{brands::SoloBrand, functions::{apply, identity}, types::Solo};
65	///
66	/// assert_eq!(apply::<SoloBrand, _, _, _>(Solo(identity))(Solo(())), Solo(()));
67	/// ```
68	fn apply<F, A, B>(ff: Apply<Self, (F,)>) -> impl Fn(Apply<Self, (A,)>) -> Apply<Self, (B,)>
69	where
70		Self: Kind<(F,)> + Kind<(A,)> + Kind<(B,)>,
71		F: Fn(A) -> B,
72		Apply<Self, (F,)>: Clone,
73	{
74		map::<Self, _, _, _>(<Self as Brand<Solo<F>, _>>::project(ff.to_owned()).0)
75	}
76}
77
78impl ApplyFirst for SoloBrand {
79	/// # Examples
80	///
81	/// ```
82	/// use fp_library::{brands::SoloBrand, functions::{apply_first, identity}, types::Solo};
83	///
84	/// assert_eq!(apply_first::<SoloBrand, _, _>(Solo(true))(Solo(false)), Solo(true));
85	/// ```
86	fn apply_first<A, B>(fa: Apply<Self, (A,)>) -> impl Fn(Apply<Self, (B,)>) -> Apply<Self, (A,)>
87	where
88		Self: Kind<(A,)> + Kind<(B,)>,
89		Apply<Self, (A,)>: Clone,
90	{
91		move |_fb| fa.to_owned()
92	}
93}
94
95impl ApplySecond for SoloBrand {
96	/// # Examples
97	///
98	/// ```
99	/// use fp_library::{brands::SoloBrand, functions::{apply_second, identity}, types::Solo};
100	///
101	/// assert_eq!(apply_second::<SoloBrand, _, _>(Solo(true))(Solo(false)), Solo(false));
102	/// ```
103	fn apply_second<A, B>(_fa: Apply<Self, (A,)>) -> impl Fn(Apply<Self, (B,)>) -> Apply<Self, (B,)>
104	where
105		Self: Kind<(A,)> + Kind<(B,)>,
106	{
107		identity
108	}
109}
110
111impl Bind for SoloBrand {
112	/// # Examples
113	///
114	/// ```
115	/// use fp_library::{brands::SoloBrand, functions::{bind, pure}, types::Solo};
116	///
117	/// assert_eq!(bind::<SoloBrand, _, _, _>(Solo(()))(pure::<SoloBrand, _>), Solo(()));
118	/// ```
119	fn bind<F, A, B>(ma: Apply<Self, (A,)>) -> impl Fn(F) -> Apply<Self, (B,)>
120	where
121		Self: Kind<(A,)> + Kind<(B,)> + Sized,
122		F: Fn(A) -> Apply<Self, (B,)>,
123		Apply<Self, (A,)>: Clone,
124	{
125		move |f| f(<Self as Brand<_, _>>::project(ma.to_owned()).0)
126	}
127}