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}