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