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