karpal_core/
comonad_store.rs1use crate::hkt::HKT;
2#[cfg(any(feature = "std", feature = "alloc"))]
3use crate::hkt::StoreF;
4
5pub trait ComonadStore<S>: HKT {
10 fn pos<A>(wa: &Self::Of<A>) -> S;
11 fn peek<A>(s: S, wa: &Self::Of<A>) -> A;
12
13 fn extract<A>(wa: &Self::Of<A>) -> A
15 where
16 S: Clone,
17 {
18 Self::peek(Self::pos(wa), wa)
19 }
20}
21
22#[cfg(any(feature = "std", feature = "alloc"))]
23impl<S: Clone + 'static> ComonadStore<S> for StoreF<S> {
24 fn pos<A>(wa: &(Box<dyn Fn(S) -> A>, S)) -> S {
25 wa.1.clone()
26 }
27
28 fn peek<A>(s: S, wa: &(Box<dyn Fn(S) -> A>, S)) -> A {
29 (wa.0)(s)
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn store_pos() {
39 let w: (Box<dyn Fn(i32) -> String>, i32) = (Box::new(|s| format!("value_{}", s)), 42);
40 assert_eq!(StoreF::<i32>::pos(&w), 42);
41 }
42
43 #[test]
44 fn store_peek() {
45 let w: (Box<dyn Fn(i32) -> String>, i32) = (Box::new(|s| format!("value_{}", s)), 42);
46 assert_eq!(StoreF::<i32>::peek(10, &w), "value_10");
47 }
48
49 #[test]
50 fn store_extract() {
51 let w: (Box<dyn Fn(i32) -> String>, i32) = (Box::new(|s| format!("value_{}", s)), 42);
52 assert_eq!(StoreF::<i32>::extract(&w), "value_42");
53 }
54}
55
56#[cfg(test)]
57mod law_tests {
58 use super::*;
59 use proptest::prelude::*;
60
61 proptest! {
62 #[test]
64 fn store_peek_pos_is_extract(s in any::<i16>()) {
65 let w: (Box<dyn Fn(i16) -> i32>, i16) =
66 (Box::new(|s| s as i32 * 2), s);
67 let pos = StoreF::<i16>::pos(&w);
68 let left = StoreF::<i16>::peek(pos, &w);
69 let right = StoreF::<i16>::extract(&w);
70 prop_assert_eq!(left, right);
71 }
72 }
73}