1use crate::hkt::HKT2;
2
3pub struct Coend<P: HKT2, A> {
23 pub value: P::P<A, A>,
25}
26
27impl<P: HKT2, A> Coend<P, A> {
28 pub fn new(value: P::P<A, A>) -> Self {
30 Coend { value }
31 }
32
33 pub fn elim<R>(self, f: impl FnOnce(P::P<A, A>) -> R) -> R {
40 f(self.value)
41 }
42}
43
44impl<P: HKT2, A: Clone> Clone for Coend<P, A>
45where
46 P::P<A, A>: Clone,
47{
48 fn clone(&self) -> Self {
49 Coend {
50 value: self.value.clone(),
51 }
52 }
53}
54
55impl<P: HKT2, A: PartialEq> PartialEq for Coend<P, A>
56where
57 P::P<A, A>: PartialEq,
58{
59 fn eq(&self, other: &Self) -> bool {
60 self.value == other.value
61 }
62}
63
64impl<P: HKT2, A: Eq> Eq for Coend<P, A> where P::P<A, A>: Eq {}
65
66impl<P: HKT2, A: core::fmt::Debug> core::fmt::Debug for Coend<P, A>
67where
68 P::P<A, A>: core::fmt::Debug,
69{
70 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
71 f.debug_struct("Coend").field("value", &self.value).finish()
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use crate::hkt::{ResultBF, TupleF};
79
80 #[test]
81 fn coend_tuple_new() {
82 let c: Coend<TupleF, i32> = Coend::new((1, 2));
83 assert_eq!(c.value, (1, 2));
84 }
85
86 #[test]
87 fn coend_tuple_elim() {
88 let c: Coend<TupleF, i32> = Coend::new((3, 4));
89 let sum = c.elim(|(a, b)| a + b);
90 assert_eq!(sum, 7);
91 }
92
93 #[test]
94 fn coend_result_new() {
95 let c: Coend<ResultBF, i32> = Coend::new(Ok(42));
96 assert_eq!(c.value, Ok(42));
97 }
98
99 #[test]
100 fn coend_clone() {
101 let c: Coend<TupleF, i32> = Coend::new((1, 2));
102 let c2 = c.clone();
103 assert_eq!(c, c2);
104 }
105
106 #[test]
107 fn coend_debug() {
108 let c: Coend<TupleF, i32> = Coend::new((1, 2));
109 let s = format!("{:?}", c);
110 assert!(s.contains("Coend"));
111 assert!(s.contains("(1, 2)"));
112 }
113}