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