karpal_core/
applicative.rs1use crate::apply::Apply;
2use crate::hkt::OptionF;
3use crate::hkt::ResultF;
4#[cfg(any(feature = "std", feature = "alloc"))]
5use crate::hkt::VecF;
6
7pub trait Applicative: Apply {
14 fn pure<A>(a: A) -> Self::Of<A>;
15}
16
17impl Applicative for OptionF {
18 fn pure<A>(a: A) -> Option<A> {
19 Some(a)
20 }
21}
22
23impl<E> Applicative for ResultF<E> {
24 fn pure<A>(a: A) -> Result<A, E> {
25 Ok(a)
26 }
27}
28
29#[cfg(any(feature = "std", feature = "alloc"))]
30impl Applicative for VecF {
31 fn pure<A>(a: A) -> Vec<A> {
32 vec![a]
33 }
34}
35
36impl Applicative for crate::hkt::IdentityF {
37 fn pure<A>(a: A) -> A {
38 a
39 }
40}
41
42#[cfg(any(feature = "std", feature = "alloc"))]
43impl Applicative for crate::hkt::NonEmptyVecF {
44 fn pure<A>(a: A) -> crate::hkt::NonEmptyVec<A> {
45 crate::hkt::NonEmptyVec::singleton(a)
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn option_pure() {
55 assert_eq!(OptionF::pure(42), Some(42));
56 }
57
58 #[test]
59 fn result_pure() {
60 assert_eq!(ResultF::<String>::pure(42), Ok(42));
61 }
62
63 #[test]
64 fn vec_pure() {
65 assert_eq!(VecF::pure(42), vec![42]);
66 }
67}
68
69#[cfg(test)]
70mod law_tests {
71 use super::*;
72 use proptest::prelude::*;
73
74 proptest! {
75 #[test]
77 fn option_identity(x in any::<Option<i32>>()) {
78 let id_fn: Option<fn(i32) -> i32> = OptionF::pure(|a| a);
79 let result = OptionF::ap(id_fn, x.clone());
80 prop_assert_eq!(result, x);
81 }
82
83 #[test]
85 fn option_homomorphism(x in any::<i32>()) {
86 let f = |a: i32| a.wrapping_add(1);
87 let left = OptionF::ap(OptionF::pure(f as fn(i32) -> i32), OptionF::pure(x));
88 let right = OptionF::pure(f(x));
89 prop_assert_eq!(left, right);
90 }
91
92 #[test]
94 fn option_interchange(y in any::<i16>()) {
95 let u: Option<fn(i16) -> i16> = Some(|a| a.wrapping_mul(2));
96 let left = OptionF::ap(u, OptionF::pure(y));
97 let right = OptionF::ap(
98 OptionF::pure(move |f: fn(i16) -> i16| f(y)),
99 Some(|a: i16| a.wrapping_mul(2) as i16),
100 );
101 prop_assert_eq!(left, right);
102 }
103
104 #[test]
105 fn vec_identity(x in prop::collection::vec(any::<i32>(), 0..10)) {
106 let id_fn: Vec<fn(i32) -> i32> = VecF::pure(|a| a);
107 let result = VecF::ap(id_fn, x.clone());
108 prop_assert_eq!(result, x);
109 }
110
111 #[test]
112 fn vec_homomorphism(x in any::<i32>()) {
113 let f = |a: i32| a.wrapping_add(1);
114 let left = VecF::ap(VecF::pure(f as fn(i32) -> i32), VecF::pure(x));
115 let right = VecF::pure(f(x));
116 prop_assert_eq!(left, right);
117 }
118 }
119}