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