fp_library/types/
identity.rs

1//! Implementations for [`Identity`], a type that wraps a value.
2
3use crate::{
4	Apply,
5	brands::IdentityBrand,
6	classes::{
7		applicative::Applicative, apply_first::ApplyFirst, apply_second::ApplySecond,
8		clonable_fn::ClonableFn, foldable::Foldable, functor::Functor, lift::Lift, monoid::Monoid,
9		pointed::Pointed, semiapplicative::Semiapplicative, semimonad::Semimonad,
10		traversable::Traversable,
11	},
12	impl_kind,
13	kinds::*,
14};
15
16/// Wraps a value.
17#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
18pub struct Identity<A>(pub A);
19
20impl_kind! {
21	for IdentityBrand {
22		type Of<'a, A: 'a>: 'a = Identity<A>;
23	}
24}
25
26impl Functor for IdentityBrand {
27	/// Maps a function over the value in the identity.
28	///
29	/// # Type Signature
30	///
31	/// `forall a b. Functor Identity => (a -> b, Identity a) -> Identity b`
32	///
33	/// # Parameters
34	///
35	/// * `f`: The function to apply.
36	/// * `fa`: The identity to map over.
37	///
38	/// # Returns
39	///
40	/// A new identity containing the result of applying the function.
41	///
42	/// # Examples
43	///
44	/// ```
45	/// use fp_library::classes::functor::map;
46	/// use fp_library::brands::IdentityBrand;
47	/// use fp_library::types::Identity;
48	///
49	/// assert_eq!(map::<IdentityBrand, _, _, _>(|x: i32| x * 2, Identity(5)), Identity(10));
50	/// ```
51	fn map<'a, A: 'a, B: 'a, F>(
52		f: F,
53		fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
54	) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
55	where
56		F: Fn(A) -> B + 'a,
57	{
58		Identity(f(fa.0))
59	}
60}
61
62impl Lift for IdentityBrand {
63	/// Lifts a binary function into the identity context.
64	///
65	/// # Type Signature
66	///
67	/// `forall a b c. Lift Identity => ((a, b) -> c, Identity a, Identity b) -> Identity c`
68	///
69	/// # Parameters
70	///
71	/// * `f`: The binary function to apply.
72	/// * `fa`: The first identity.
73	/// * `fb`: The second identity.
74	///
75	/// # Returns
76	///
77	/// A new identity containing the result of applying the function.
78	///
79	/// # Examples
80	///
81	/// ```
82	/// use fp_library::classes::lift::lift2;
83	/// use fp_library::brands::IdentityBrand;
84	/// use fp_library::types::Identity;
85	///
86	/// assert_eq!(
87	///     lift2::<IdentityBrand, _, _, _, _>(|x: i32, y: i32| x + y, Identity(1), Identity(2)),
88	///     Identity(3)
89	/// );
90	/// ```
91	fn lift2<'a, A, B, C, F>(
92		f: F,
93		fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
94		fb: Apply!(brand: Self, signature: ('a, B: 'a) -> 'a),
95	) -> Apply!(brand: Self, signature: ('a, C: 'a) -> 'a)
96	where
97		F: Fn(A, B) -> C + 'a,
98		A: 'a,
99		B: 'a,
100		C: 'a,
101	{
102		Identity(f(fa.0, fb.0))
103	}
104}
105
106impl Pointed for IdentityBrand {
107	/// Wraps a value in an identity.
108	///
109	/// # Type Signature
110	///
111	/// `forall a. Pointed Identity => a -> Identity a`
112	///
113	/// # Parameters
114	///
115	/// * `a`: The value to wrap.
116	///
117	/// # Returns
118	///
119	/// An identity containing the value.
120	///
121	/// # Examples
122	///
123	/// ```
124	/// use fp_library::classes::pointed::pure;
125	/// use fp_library::brands::IdentityBrand;
126	/// use fp_library::types::Identity;
127	///
128	/// assert_eq!(pure::<IdentityBrand, _>(5), Identity(5));
129	/// ```
130	fn pure<'a, A: 'a>(a: A) -> Apply!(brand: Self, signature: ('a, A: 'a) -> 'a) {
131		Identity(a)
132	}
133}
134
135impl ApplyFirst for IdentityBrand {}
136impl ApplySecond for IdentityBrand {}
137
138impl Semiapplicative for IdentityBrand {
139	/// Applies a wrapped function to a wrapped value.
140	///
141	/// # Type Signature
142	///
143	/// `forall a b. Semiapplicative Identity => (Identity (a -> b), Identity a) -> Identity b`
144	///
145	/// # Parameters
146	///
147	/// * `ff`: The identity containing the function.
148	/// * `fa`: The identity containing the value.
149	///
150	/// # Returns
151	///
152	/// A new identity containing the result of applying the function.
153	///
154	/// # Examples
155	///
156	/// ```
157	/// use fp_library::classes::semiapplicative::apply;
158	/// use fp_library::classes::clonable_fn::ClonableFn;
159	/// use fp_library::brands::{IdentityBrand};
160	/// use fp_library::types::Identity;
161	/// use fp_library::brands::RcFnBrand;
162	/// use std::rc::Rc;
163	///
164	/// let f = Identity(<RcFnBrand as ClonableFn>::new(|x: i32| x * 2));
165	/// assert_eq!(apply::<IdentityBrand, _, _, RcFnBrand>(f, Identity(5)), Identity(10));
166	/// ```
167	fn apply<'a, A: 'a + Clone, B: 'a, FnBrand: 'a + ClonableFn>(
168		ff: Apply!(brand: Self, signature: ('a, Apply!(brand: FnBrand, kind: ClonableFn, lifetimes: ('a), types: (A, B)): 'a) -> 'a),
169		fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
170	) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) {
171		Identity(ff.0(fa.0))
172	}
173}
174
175impl Semimonad for IdentityBrand {
176	/// Chains identity computations.
177	///
178	/// # Type Signature
179	///
180	/// `forall a b. Semimonad Identity => (Identity a, a -> Identity b) -> Identity b`
181	///
182	/// # Parameters
183	///
184	/// * `ma`: The first identity.
185	/// * `f`: The function to apply to the value inside the identity.
186	///
187	/// # Returns
188	///
189	/// The result of applying `f` to the value.
190	///
191	/// # Examples
192	///
193	/// ```
194	/// use fp_library::classes::semimonad::bind;
195	/// use fp_library::brands::IdentityBrand;
196	/// use fp_library::types::Identity;
197	///
198	/// assert_eq!(
199	///     bind::<IdentityBrand, _, _, _>(Identity(5), |x| Identity(x * 2)),
200	///     Identity(10)
201	/// );
202	/// ```
203	fn bind<'a, A: 'a, B: 'a, F>(
204		ma: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
205		f: F,
206	) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
207	where
208		F: Fn(A) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) + 'a,
209	{
210		f(ma.0)
211	}
212}
213
214impl Foldable for IdentityBrand {
215	/// Folds the identity from the right.
216	///
217	/// # Type Signature
218	///
219	/// `forall a b. Foldable Identity => ((a, b) -> b, b, Identity a) -> b`
220	///
221	/// # Parameters
222	///
223	/// * `f`: The folding function.
224	/// * `init`: The initial value.
225	/// * `fa`: The identity to fold.
226	///
227	/// # Returns
228	///
229	/// `f(a, init)`.
230	///
231	/// # Examples
232	///
233	/// ```
234	/// use fp_library::classes::foldable::fold_right;
235	/// use fp_library::brands::IdentityBrand;
236	/// use fp_library::types::Identity;
237	///
238	/// assert_eq!(fold_right::<IdentityBrand, _, _, _>(|x: i32, acc| x + acc, 0, Identity(5)), 5);
239	/// ```
240	fn fold_right<'a, A: 'a, B: 'a, F>(
241		f: F,
242		init: B,
243		fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
244	) -> B
245	where
246		F: Fn(A, B) -> B + 'a,
247	{
248		f(fa.0, init)
249	}
250
251	/// Folds the identity from the left.
252	///
253	/// # Type Signature
254	///
255	/// `forall a b. Foldable Identity => ((b, a) -> b, b, Identity a) -> b`
256	///
257	/// # Parameters
258	///
259	/// * `f`: The folding function.
260	/// * `init`: The initial value.
261	/// * `fa`: The identity to fold.
262	///
263	/// # Returns
264	///
265	/// `f(init, a)`.
266	///
267	/// # Examples
268	///
269	/// ```
270	/// use fp_library::classes::foldable::fold_left;
271	/// use fp_library::brands::IdentityBrand;
272	/// use fp_library::types::Identity;
273	///
274	/// assert_eq!(fold_left::<IdentityBrand, _, _, _>(|acc, x: i32| acc + x, 0, Identity(5)), 5);
275	/// ```
276	fn fold_left<'a, A: 'a, B: 'a, F>(
277		f: F,
278		init: B,
279		fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
280	) -> B
281	where
282		F: Fn(B, A) -> B + 'a,
283	{
284		f(init, fa.0)
285	}
286
287	/// Maps the value to a monoid and returns it.
288	///
289	/// # Type Signature
290	///
291	/// `forall a m. (Foldable Identity, Monoid m) => ((a) -> m, Identity a) -> m`
292	///
293	/// # Parameters
294	///
295	/// * `f`: The mapping function.
296	/// * `fa`: The identity to fold.
297	///
298	/// # Returns
299	///
300	/// `f(a)`.
301	///
302	/// # Examples
303	///
304	/// ```
305	/// use fp_library::classes::foldable::fold_map;
306	/// use fp_library::brands::IdentityBrand;
307	/// use fp_library::types::Identity;
308	/// use fp_library::types::string; // Import to bring Monoid impl for String into scope
309	///
310	/// assert_eq!(fold_map::<IdentityBrand, _, _, _>(|x: i32| x.to_string(), Identity(5)), "5".to_string());
311	/// ```
312	fn fold_map<'a, A: 'a, M, F>(
313		f: F,
314		fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
315	) -> M
316	where
317		M: Monoid + 'a,
318		F: Fn(A) -> M + 'a,
319	{
320		f(fa.0)
321	}
322}
323
324impl Traversable for IdentityBrand {
325	/// Traverses the identity with an applicative function.
326	///
327	/// # Type Signature
328	///
329	/// `forall a b f. (Traversable Identity, Applicative f) => (a -> f b, Identity a) -> f (Identity b)`
330	///
331	/// # Parameters
332	///
333	/// * `f`: The function to apply.
334	/// * `ta`: The identity to traverse.
335	///
336	/// # Returns
337	///
338	/// The identity wrapped in the applicative context.
339	///
340	/// # Examples
341	///
342	/// ```
343	/// use fp_library::classes::traversable::traverse;
344	/// use fp_library::brands::{IdentityBrand, OptionBrand};
345	/// use fp_library::types::Identity;
346	///
347	/// assert_eq!(
348	///     traverse::<IdentityBrand, OptionBrand, _, _, _>(|x| Some(x * 2), Identity(5)),
349	///     Some(Identity(10))
350	/// );
351	/// ```
352	fn traverse<'a, F: Applicative, A: 'a + Clone, B: 'a + Clone, Func>(
353		f: Func,
354		ta: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
355	) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): 'a) -> 'a)
356	where
357		Func: Fn(A) -> Apply!(brand: F, signature: ('a, B: 'a) -> 'a) + 'a,
358		Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): Clone,
359	{
360		F::map(|b| Identity(b), f(ta.0))
361	}
362
363	/// Sequences an identity of applicative.
364	///
365	/// # Type Signature
366	///
367	/// `forall a f. (Traversable Identity, Applicative f) => (Identity (f a)) -> f (Identity a)`
368	///
369	/// # Parameters
370	///
371	/// * `ta`: The identity containing the applicative value.
372	///
373	/// # Returns
374	///
375	/// The identity wrapped in the applicative context.
376	///
377	/// # Examples
378	///
379	/// ```
380	/// use fp_library::classes::traversable::sequence;
381	/// use fp_library::brands::{IdentityBrand, OptionBrand};
382	/// use fp_library::types::Identity;
383	///
384	/// assert_eq!(
385	///     sequence::<IdentityBrand, OptionBrand, _>(Identity(Some(5))),
386	///     Some(Identity(5))
387	/// );
388	/// ```
389	fn sequence<'a, F: Applicative, A: 'a + Clone>(
390		ta: Apply!(brand: Self, signature: ('a, Apply!(brand: F, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
391	) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
392	where
393		Apply!(brand: F, signature: ('a, A: 'a) -> 'a): Clone,
394		Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): Clone,
395	{
396		F::map(|a| Identity(a), ta.0)
397	}
398}
399
400#[cfg(test)]
401mod tests {
402	use super::*;
403	use crate::{
404		brands::{OptionBrand, RcFnBrand},
405		classes::{functor::map, pointed::pure, semiapplicative::apply, semimonad::bind},
406		functions::{compose, identity},
407	};
408	use quickcheck_macros::quickcheck;
409
410	// Functor Laws
411
412	/// Tests the identity law for Functor.
413	#[quickcheck]
414	fn functor_identity(x: i32) -> bool {
415		let x = Identity(x);
416		map::<IdentityBrand, _, _, _>(identity, x) == x
417	}
418
419	/// Tests the composition law for Functor.
420	#[quickcheck]
421	fn functor_composition(x: i32) -> bool {
422		let x = Identity(x);
423		let f = |x: i32| x.wrapping_add(1);
424		let g = |x: i32| x.wrapping_mul(2);
425		map::<IdentityBrand, _, _, _>(compose(f, g), x)
426			== map::<IdentityBrand, _, _, _>(f, map::<IdentityBrand, _, _, _>(g, x))
427	}
428
429	// Applicative Laws
430
431	/// Tests the identity law for Applicative.
432	#[quickcheck]
433	fn applicative_identity(v: i32) -> bool {
434		let v = Identity(v);
435		apply::<IdentityBrand, _, _, RcFnBrand>(
436			pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(identity)),
437			v,
438		) == v
439	}
440
441	/// Tests the homomorphism law for Applicative.
442	#[quickcheck]
443	fn applicative_homomorphism(x: i32) -> bool {
444		let f = |x: i32| x.wrapping_mul(2);
445		apply::<IdentityBrand, _, _, RcFnBrand>(
446			pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(f)),
447			pure::<IdentityBrand, _>(x),
448		) == pure::<IdentityBrand, _>(f(x))
449	}
450
451	/// Tests the composition law for Applicative.
452	#[quickcheck]
453	fn applicative_composition(
454		w: i32,
455		u_val: i32,
456		v_val: i32,
457	) -> bool {
458		let w = Identity(w);
459		let v_fn = move |x: i32| x.wrapping_mul(v_val);
460		let u_fn = move |x: i32| x.wrapping_add(u_val);
461
462		let v = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(v_fn));
463		let u = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(u_fn));
464
465		// RHS: u <*> (v <*> w)
466		let vw = apply::<IdentityBrand, _, _, RcFnBrand>(v.clone(), w.clone());
467		let rhs = apply::<IdentityBrand, _, _, RcFnBrand>(u.clone(), vw);
468
469		// LHS: pure(compose) <*> u <*> v <*> w
470		// equivalent to (u . v) <*> w
471		let composed = move |x| u_fn(v_fn(x));
472		let uv = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(composed));
473
474		let lhs = apply::<IdentityBrand, _, _, RcFnBrand>(uv, w);
475
476		lhs == rhs
477	}
478
479	/// Tests the interchange law for Applicative.
480	#[quickcheck]
481	fn applicative_interchange(y: i32) -> bool {
482		// u <*> pure y = pure ($ y) <*> u
483		let f = |x: i32| x.wrapping_mul(2);
484		let u = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(f));
485
486		let lhs = apply::<IdentityBrand, _, _, RcFnBrand>(u.clone(), pure::<IdentityBrand, _>(y));
487
488		let rhs_fn = <RcFnBrand as ClonableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
489		let rhs = apply::<IdentityBrand, _, _, RcFnBrand>(pure::<IdentityBrand, _>(rhs_fn), u);
490
491		lhs == rhs
492	}
493
494	// Monad Laws
495
496	/// Tests the left identity law for Monad.
497	#[quickcheck]
498	fn monad_left_identity(a: i32) -> bool {
499		let f = |x: i32| Identity(x.wrapping_mul(2));
500		bind::<IdentityBrand, _, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
501	}
502
503	/// Tests the right identity law for Monad.
504	#[quickcheck]
505	fn monad_right_identity(m: i32) -> bool {
506		let m = Identity(m);
507		bind::<IdentityBrand, _, _, _>(m, pure::<IdentityBrand, _>) == m
508	}
509
510	/// Tests the associativity law for Monad.
511	#[quickcheck]
512	fn monad_associativity(m: i32) -> bool {
513		let m = Identity(m);
514		let f = |x: i32| Identity(x.wrapping_mul(2));
515		let g = |x: i32| Identity(x.wrapping_add(1));
516		bind::<IdentityBrand, _, _, _>(bind::<IdentityBrand, _, _, _>(m, f), g)
517			== bind::<IdentityBrand, _, _, _>(m, |x| bind::<IdentityBrand, _, _, _>(f(x), g))
518	}
519
520	// Edge Cases
521
522	/// Tests the `map` function.
523	#[test]
524	fn map_test() {
525		assert_eq!(map::<IdentityBrand, _, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
526	}
527
528	/// Tests the `bind` function.
529	#[test]
530	fn bind_test() {
531		assert_eq!(bind::<IdentityBrand, _, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
532	}
533
534	/// Tests the `fold_right` function.
535	#[test]
536	fn fold_right_test() {
537		assert_eq!(
538			crate::classes::foldable::fold_right::<IdentityBrand, _, _, _>(
539				|x: i32, acc| x + acc,
540				0,
541				Identity(1)
542			),
543			1
544		);
545	}
546
547	/// Tests the `fold_left` function.
548	#[test]
549	fn fold_left_test() {
550		assert_eq!(
551			crate::classes::foldable::fold_left::<IdentityBrand, _, _, _>(
552				|acc, x: i32| acc + x,
553				0,
554				Identity(1)
555			),
556			1
557		);
558	}
559
560	/// Tests the `traverse` function.
561	#[test]
562	fn traverse_test() {
563		assert_eq!(
564			crate::classes::traversable::traverse::<IdentityBrand, OptionBrand, _, _, _>(
565				|x: i32| Some(x + 1),
566				Identity(1)
567			),
568			Some(Identity(2))
569		);
570	}
571}