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