deep_causality_haft/
utils_tests.rs

1//! This module provides utility types and implementations primarily used for testing
2//! and demonstrating the type-encoded effect system within `deep_causality_haft`.
3//!
4//! These types serve as concrete examples of how to implement the `EffectN` and
5//! `MonadEffectN` traits for various arities, showcasing error propagation, warning
6//! accumulation, and other side-effect handling.
7
8use crate::{
9    Applicative, Effect3, Effect4, Effect5, Functor, Monad, MonadEffect3, MonadEffect4,
10    MonadEffect5,
11};
12use crate::{HKT, HKT3, HKT4, HKT5, Placeholder};
13
14// --- MonadEffect3 Setup ---
15
16/// A custom effect type for arity 3, used in tests and examples.
17///
18/// This struct demonstrates how to combine a primary `value`, an optional `error`,
19/// and a list of `warnings` within a single effectful context.
20#[derive(Debug, PartialEq)]
21pub struct MyCustomEffectType<T, E, W> {
22    pub value: T,
23    pub error: Option<E>,
24    pub warnings: Vec<W>,
25}
26
27/// HKT witness for `MyCustomEffectType` with two fixed parameters (Error `E` and Warning `W`).
28///
29/// This witness allows `MyCustomEffectType` to be used with `HKT` and `HKT3` traits,
30/// enabling its integration into the functional programming abstractions.
31pub struct MyEffectHktWitness<E, W>(Placeholder, E, W);
32
33impl<E, W> HKT for MyEffectHktWitness<E, W> {
34    type Type<T> = MyCustomEffectType<T, E, W>;
35}
36
37impl<E, W> HKT3<E, W> for MyEffectHktWitness<E, W> {
38    type Type<T> = MyCustomEffectType<T, E, W>;
39}
40
41/// A concrete implementation of `Effect3` for testing purposes.
42///
43/// This struct defines the fixed types for `Fixed1` (Error as `String`)
44/// and `Fixed2` (Warning as `String`), and specifies `MyEffectHktWitness`
45/// as its HKT witness.
46pub struct MyEffect;
47
48impl Effect3 for MyEffect {
49    type Fixed1 = String;
50    type Fixed2 = String;
51    type HktWitness = MyEffectHktWitness<Self::Fixed1, Self::Fixed2>;
52}
53
54impl Functor<MyEffectHktWitness<String, String>> for MyEffectHktWitness<String, String> {
55    fn fmap<A, B, Func>(
56        m_a: MyCustomEffectType<A, String, String>,
57        f: Func,
58    ) -> MyCustomEffectType<B, String, String>
59    where
60        Func: FnOnce(A) -> B,
61    {
62        MyCustomEffectType {
63            value: f(m_a.value),
64            error: m_a.error,
65            warnings: m_a.warnings,
66        }
67    }
68}
69
70impl Applicative<MyEffectHktWitness<String, String>> for MyEffectHktWitness<String, String> {
71    fn pure<T>(value: T) -> MyCustomEffectType<T, String, String> {
72        MyCustomEffectType {
73            value,
74            error: None,
75            warnings: Vec::new(),
76        }
77    }
78
79    fn apply<A, B, Func>(
80        mut f_ab: MyCustomEffectType<Func, String, String>,
81        f_a: MyCustomEffectType<A, String, String>,
82    ) -> MyCustomEffectType<B, String, String>
83    where
84        Func: FnMut(A) -> B,
85    {
86        if f_ab.error.is_some() {
87            return MyCustomEffectType {
88                value: (f_ab.value)(f_a.value), // Dummy call to satisfy type, actual value discarded
89                error: f_ab.error,
90                warnings: f_ab.warnings,
91            };
92        }
93        if f_a.error.is_some() {
94            return MyCustomEffectType {
95                value: (f_ab.value)(f_a.value), // Dummy call to satisfy type, actual value discarded
96                error: f_a.error,
97                warnings: f_a.warnings,
98            };
99        }
100
101        let mut combined_warnings = f_ab.warnings;
102        combined_warnings.extend(f_a.warnings);
103
104        MyCustomEffectType {
105            value: (f_ab.value)(f_a.value),
106            error: None,
107            warnings: combined_warnings,
108        }
109    }
110}
111
112impl Monad<MyEffectHktWitness<String, String>> for MyEffectHktWitness<String, String> {
113    fn bind<A, B, Func>(
114        m_a: MyCustomEffectType<A, String, String>,
115        f: Func,
116    ) -> MyCustomEffectType<B, String, String>
117    where
118        Func: FnOnce(A) -> MyCustomEffectType<B, String, String>,
119    {
120        if m_a.error.is_some() {
121            return MyCustomEffectType {
122                value: f(m_a.value).value,
123                error: m_a.error,
124                warnings: m_a.warnings,
125            };
126        }
127        let mut next_effect = f(m_a.value);
128        let mut combined_warnings = m_a.warnings;
129        combined_warnings.extend(next_effect.warnings);
130        next_effect.warnings = combined_warnings;
131        next_effect
132    }
133}
134
135/// A concrete implementation of `MonadEffect3` for testing purposes.
136///
137/// This struct provides the `pure` and `bind` operations for `MyEffect`,
138/// demonstrating how monadic operations work with the arity 3 effect system.
139pub struct MyMonadEffect3;
140
141impl MonadEffect3<MyEffect> for MyMonadEffect3 {
142    fn pure<T>(
143        value: T,
144    ) -> <<MyEffect as Effect3>::HktWitness as HKT3<
145        <MyEffect as Effect3>::Fixed1,
146        <MyEffect as Effect3>::Fixed2,
147    >>::Type<T> {
148        <MyEffect as Effect3>::HktWitness::pure(value)
149    }
150
151    fn bind<T, U, Func>(
152        effect: <<MyEffect as Effect3>::HktWitness as HKT3<
153            <MyEffect as Effect3>::Fixed1,
154            <MyEffect as Effect3>::Fixed2,
155        >>::Type<T>,
156        f: Func,
157    ) -> <<MyEffect as Effect3>::HktWitness as HKT3<
158        <MyEffect as Effect3>::Fixed1,
159        <MyEffect as Effect3>::Fixed2,
160    >>::Type<U>
161    where
162        Func: FnMut(
163            T,
164        ) -> <<MyEffect as Effect3>::HktWitness as HKT3<
165            <MyEffect as Effect3>::Fixed1,
166            <MyEffect as Effect3>::Fixed2,
167        >>::Type<U>,
168    {
169        <MyEffect as Effect3>::HktWitness::bind(effect, f)
170    }
171}
172
173/// A trait for adding log functionality to an arity 3 effect system.
174///
175/// This trait extends `MonadEffect3` by providing a `log` method,
176/// allowing for the accumulation of log messages (warnings) within the effect.
177pub trait LoggableEffect3<E: Effect3>: MonadEffect3<E>
178where
179    E::HktWitness: Functor<E::HktWitness> + Sized,
180{
181    /// Adds a log message to the effect's warnings.
182    ///
183    /// # Arguments
184    ///
185    /// *   `effect`: The effect to add the log message to.
186    /// *   `log`: The log message to add.
187    ///
188    /// # Returns
189    ///
190    /// The modified effect with the log message appended.
191    fn log<T>(
192        effect: <E::HktWitness as HKT3<E::Fixed1, E::Fixed2>>::Type<T>,
193        log: E::Fixed2,
194    ) -> <E::HktWitness as HKT3<E::Fixed1, E::Fixed2>>::Type<T>;
195}
196
197impl LoggableEffect3<MyEffect> for MyMonadEffect3 {
198    fn log<T>(
199        mut effect: <<MyEffect as Effect3>::HktWitness as HKT3<
200            <MyEffect as Effect3>::Fixed1,
201            <MyEffect as Effect3>::Fixed2,
202        >>::Type<T>,
203        log: <MyEffect as Effect3>::Fixed2,
204    ) -> <<MyEffect as Effect3>::HktWitness as HKT3<
205        <MyEffect as Effect3>::Fixed1,
206        <MyEffect as Effect3>::Fixed2,
207    >>::Type<T> {
208        effect.warnings.push(log);
209        effect
210    }
211}
212
213// --- MonadEffect4 Setup ---
214
215/// A custom effect type for arity 4, used in tests and examples.
216///
217/// This struct extends `MyCustomEffectType` by adding a third fixed field `f3`,
218/// demonstrating how to combine a primary `value`, an optional `f1` (error),
219/// a list of `f2` (logs), and a list of `f3` (counters) within a single effectful context.
220#[derive(Debug, PartialEq)]
221pub struct MyCustomEffectType4<T, F1, F2, F3> {
222    pub value: T,
223    pub f1: Option<F1>,
224    pub f2: Vec<F2>,
225    pub f3: Vec<F3>,
226}
227
228/// HKT witness for `MyCustomEffectType4` with three fixed parameters (`F1`, `F2`, `F3`).
229///
230/// This witness allows `MyCustomEffectType4` to be used with `HKT` and `HKT4` traits.
231pub struct MyEffectHktWitness4<F1, F2, F3>(Placeholder, F1, F2, F3);
232
233impl<F1, F2, F3> HKT for MyEffectHktWitness4<F1, F2, F3> {
234    type Type<T> = MyCustomEffectType4<T, F1, F2, F3>;
235}
236
237impl<F1, F2, F3> HKT4<F1, F2, F3> for MyEffectHktWitness4<F1, F2, F3> {
238    type Type<T> = MyCustomEffectType4<T, F1, F2, F3>;
239}
240
241/// A concrete implementation of `Effect4` for testing purposes.
242///
243/// This struct defines the fixed types for `Fixed1` (Error as `String`),
244/// `Fixed2` (Log as `String`), and `Fixed3` (Counter as `u64`), and specifies
245/// `MyEffectHktWitness4` as its HKT witness.
246pub struct MyEffect4;
247
248impl Effect4 for MyEffect4 {
249    type Fixed1 = String; // Error
250    type Fixed2 = String; // Log
251    type Fixed3 = u64; // Counter
252    type HktWitness = MyEffectHktWitness4<Self::Fixed1, Self::Fixed2, Self::Fixed3>;
253}
254
255impl Functor<MyEffectHktWitness4<String, String, u64>>
256    for MyEffectHktWitness4<String, String, u64>
257{
258    fn fmap<A, B, Func>(
259        m_a: MyCustomEffectType4<A, String, String, u64>,
260        f: Func,
261    ) -> MyCustomEffectType4<B, String, String, u64>
262    where
263        Func: FnOnce(A) -> B,
264    {
265        MyCustomEffectType4 {
266            value: f(m_a.value),
267            f1: m_a.f1,
268            f2: m_a.f2,
269            f3: m_a.f3,
270        }
271    }
272}
273
274impl Applicative<MyEffectHktWitness4<String, String, u64>>
275    for MyEffectHktWitness4<String, String, u64>
276{
277    fn pure<T>(value: T) -> MyCustomEffectType4<T, String, String, u64> {
278        MyCustomEffectType4 {
279            value,
280            f1: None,
281            f2: Vec::new(),
282            f3: Vec::new(),
283        }
284    }
285
286    fn apply<A, B, Func>(
287        mut f_ab: MyCustomEffectType4<Func, String, String, u64>,
288        f_a: MyCustomEffectType4<A, String, String, u64>,
289    ) -> MyCustomEffectType4<B, String, String, u64>
290    where
291        Func: FnMut(A) -> B,
292    {
293        if f_ab.f1.is_some() {
294            return MyCustomEffectType4 {
295                value: (f_ab.value)(f_a.value), // Dummy call to satisfy type
296                f1: f_ab.f1,
297                f2: f_ab.f2,
298                f3: f_ab.f3,
299            };
300        }
301        if f_a.f1.is_some() {
302            return MyCustomEffectType4 {
303                value: (f_ab.value)(f_a.value), // Dummy call to satisfy type
304                f1: f_a.f1,
305                f2: f_a.f2,
306                f3: f_a.f3,
307            };
308        }
309
310        let mut combined_f2 = f_ab.f2;
311        combined_f2.extend(f_a.f2);
312
313        let mut combined_f3 = f_ab.f3;
314        combined_f3.extend(f_a.f3);
315
316        MyCustomEffectType4 {
317            value: (f_ab.value)(f_a.value),
318            f1: None,
319            f2: combined_f2,
320            f3: combined_f3,
321        }
322    }
323}
324
325impl Monad<MyEffectHktWitness4<String, String, u64>> for MyEffectHktWitness4<String, String, u64> {
326    fn bind<A, B, Func>(
327        m_a: MyCustomEffectType4<A, String, String, u64>,
328        f: Func,
329    ) -> MyCustomEffectType4<B, String, String, u64>
330    where
331        Func: FnOnce(A) -> MyCustomEffectType4<B, String, String, u64>,
332    {
333        if m_a.f1.is_some() {
334            return MyCustomEffectType4 {
335                value: f(m_a.value).value, // Need a value of type B
336                f1: m_a.f1,
337                f2: m_a.f2,
338                f3: m_a.f3,
339            };
340        }
341        let mut next_effect = f(m_a.value);
342        let mut combined_f2 = m_a.f2;
343        combined_f2.extend(next_effect.f2);
344        next_effect.f2 = combined_f2;
345
346        let mut combined_f3 = m_a.f3;
347        combined_f3.extend(next_effect.f3);
348        next_effect.f3 = combined_f3;
349
350        next_effect
351    }
352}
353
354/// A concrete implementation of `MonadEffect4` for testing purposes.
355///
356/// This struct provides the `pure` and `bind` operations for `MyEffect4`,
357/// demonstrating how monadic operations work with the arity 4 effect system.
358pub struct MyMonadEffect4;
359
360impl MonadEffect4<MyEffect4> for MyMonadEffect4 {
361    fn pure<T>(
362        value: T,
363    ) -> <<MyEffect4 as Effect4>::HktWitness as HKT4<
364        <MyEffect4 as Effect4>::Fixed1,
365        <MyEffect4 as Effect4>::Fixed2,
366        <MyEffect4 as Effect4>::Fixed3,
367    >>::Type<T> {
368        <MyEffect4 as Effect4>::HktWitness::pure(value)
369    }
370
371    fn bind<T, U, Func>(
372        effect: <<MyEffect4 as Effect4>::HktWitness as HKT4<
373            <MyEffect4 as Effect4>::Fixed1,
374            <MyEffect4 as Effect4>::Fixed2,
375            <MyEffect4 as Effect4>::Fixed3,
376        >>::Type<T>,
377        f: Func,
378    ) -> <<MyEffect4 as Effect4>::HktWitness as HKT4<
379        <MyEffect4 as Effect4>::Fixed1,
380        <MyEffect4 as Effect4>::Fixed2,
381        <MyEffect4 as Effect4>::Fixed3,
382    >>::Type<U>
383    where
384        Func: FnMut(
385            T,
386        ) -> <<MyEffect4 as Effect4>::HktWitness as HKT4<
387            <MyEffect4 as Effect4>::Fixed1,
388            <MyEffect4 as Effect4>::Fixed2,
389            <MyEffect4 as Effect4>::Fixed3,
390        >>::Type<U>,
391    {
392        <MyEffect4 as Effect4>::HktWitness::bind(effect, f)
393    }
394}
395
396/// A trait for adding log functionality to an arity 4 effect system.
397///
398/// This trait extends `MonadEffect4` by providing a `log` method,
399/// allowing for the accumulation of log messages (counters) within the effect.
400pub trait LoggableEffect4<E: Effect4>: MonadEffect4<E>
401where
402    E::HktWitness: Functor<E::HktWitness> + Sized,
403{
404    /// Adds a log message (counter) to the effect's `f3` field.
405    ///
406    /// # Arguments
407    ///
408    /// *   `effect`: The effect to add the log message to.
409    /// *   `log`: The log message (counter value) to add.
410    ///
411    /// # Returns
412    ///
413    /// The modified effect with the log message appended.
414    fn log<T>(
415        effect: <E::HktWitness as HKT4<E::Fixed1, E::Fixed2, E::Fixed3>>::Type<T>,
416        log: E::Fixed3,
417    ) -> <E::HktWitness as HKT4<E::Fixed1, E::Fixed2, E::Fixed3>>::Type<T>;
418}
419
420impl LoggableEffect4<MyEffect4> for MyMonadEffect4 {
421    fn log<T>(
422        mut effect: <<MyEffect4 as Effect4>::HktWitness as HKT4<
423            <MyEffect4 as Effect4>::Fixed1,
424            <MyEffect4 as Effect4>::Fixed2,
425            <MyEffect4 as Effect4>::Fixed3,
426        >>::Type<T>,
427        log: <MyEffect4 as Effect4>::Fixed3,
428    ) -> <<MyEffect4 as Effect4>::HktWitness as HKT4<
429        <MyEffect4 as Effect4>::Fixed1,
430        <MyEffect4 as Effect4>::Fixed2,
431        <MyEffect4 as Effect4>::Fixed3,
432    >>::Type<T> {
433        effect.f3.push(log);
434        effect
435    }
436}
437
438// --- MonadEffect5 Setup ---
439
440/// A custom effect type for arity 5, used in tests and examples.
441///
442/// This struct extends `MyCustomEffectType4` by adding a fourth fixed field `f4`,
443/// demonstrating how to combine a primary `value`, an optional `f1` (error),
444/// a list of `f2` (logs), a list of `f3` (counters), and a list of `f4` (traces)
445/// within a single effectful context.
446#[derive(Debug, PartialEq)]
447pub struct MyCustomEffectType5<T, F1, F2, F3, F4> {
448    pub value: T,
449    pub f1: Option<F1>,
450    pub f2: Vec<F2>,
451    pub f3: Vec<F3>,
452    pub f4: Vec<F4>,
453}
454
455/// HKT witness for `MyCustomEffectType5` with four fixed parameters (`F1`, `F2`, `F3`, `F4`).
456///
457/// This witness allows `MyCustomEffectType5` to be used with `HKT` and `HKT5` traits.
458pub struct MyEffectHktWitness5<F1, F2, F3, F4>(Placeholder, F1, F2, F3, F4);
459
460impl<F1, F2, F3, F4> HKT for MyEffectHktWitness5<F1, F2, F3, F4> {
461    type Type<T> = MyCustomEffectType5<T, F1, F2, F3, F4>;
462}
463
464impl<F1, F2, F3, F4> HKT5<F1, F2, F3, F4> for MyEffectHktWitness5<F1, F2, F3, F4> {
465    type Type<T> = MyCustomEffectType5<T, F1, F2, F3, F4>;
466}
467
468/// A concrete implementation of `Effect5` for testing purposes.
469///
470/// This struct defines the fixed types for `Fixed1` (Error as `String`),
471/// `Fixed2` (Log as `String`), `Fixed3` (Counter as `u64`), and `Fixed4` (Trace as `String`),
472/// and specifies `MyEffectHktWitness5` as its HKT witness.
473pub struct MyEffect5;
474
475impl Effect5 for MyEffect5 {
476    type Fixed1 = String;
477    type Fixed2 = String;
478    type Fixed3 = u64;
479    type Fixed4 = String;
480    type HktWitness = MyEffectHktWitness5<Self::Fixed1, Self::Fixed2, Self::Fixed3, Self::Fixed4>;
481}
482
483impl Functor<MyEffectHktWitness5<String, String, u64, String>>
484    for MyEffectHktWitness5<String, String, u64, String>
485{
486    fn fmap<A, B, Func>(
487        m_a: MyCustomEffectType5<A, String, String, u64, String>,
488        f: Func,
489    ) -> MyCustomEffectType5<B, String, String, u64, String>
490    where
491        Func: FnOnce(A) -> B,
492    {
493        MyCustomEffectType5 {
494            value: f(m_a.value),
495            f1: m_a.f1,
496            f2: m_a.f2,
497            f3: m_a.f3,
498            f4: m_a.f4,
499        }
500    }
501}
502
503impl Applicative<MyEffectHktWitness5<String, String, u64, String>>
504    for MyEffectHktWitness5<String, String, u64, String>
505{
506    fn pure<T>(value: T) -> MyCustomEffectType5<T, String, String, u64, String> {
507        MyCustomEffectType5 {
508            value,
509            f1: None,
510            f2: Vec::new(),
511            f3: Vec::new(),
512            f4: Vec::new(),
513        }
514    }
515
516    fn apply<A, B, Func>(
517        mut f_ab: MyCustomEffectType5<Func, String, String, u64, String>,
518        f_a: MyCustomEffectType5<A, String, String, u64, String>,
519    ) -> MyCustomEffectType5<B, String, String, u64, String>
520    where
521        Func: FnMut(A) -> B,
522    {
523        if f_ab.f1.is_some() {
524            return MyCustomEffectType5 {
525                value: (f_ab.value)(f_a.value), // Dummy call to satisfy type
526                f1: f_ab.f1,
527                f2: f_ab.f2,
528                f3: f_ab.f3,
529                f4: f_ab.f4,
530            };
531        }
532        if f_a.f1.is_some() {
533            return MyCustomEffectType5 {
534                value: (f_ab.value)(f_a.value), // Dummy call to satisfy type
535                f1: f_a.f1,
536                f2: f_a.f2,
537                f3: f_a.f3,
538                f4: f_a.f4,
539            };
540        }
541
542        let mut combined_f2 = f_ab.f2;
543        combined_f2.extend(f_a.f2);
544
545        let mut combined_f3 = f_ab.f3;
546        combined_f3.extend(f_a.f3);
547
548        let mut combined_f4 = f_ab.f4;
549        combined_f4.extend(f_a.f4);
550
551        MyCustomEffectType5 {
552            value: (f_ab.value)(f_a.value),
553            f1: None,
554            f2: combined_f2,
555            f3: combined_f3,
556            f4: combined_f4,
557        }
558    }
559}
560
561impl Monad<MyEffectHktWitness5<String, String, u64, String>>
562    for MyEffectHktWitness5<String, String, u64, String>
563{
564    fn bind<A, B, Func>(
565        m_a: MyCustomEffectType5<A, String, String, u64, String>,
566        f: Func,
567    ) -> MyCustomEffectType5<B, String, String, u64, String>
568    where
569        Func: FnOnce(A) -> MyCustomEffectType5<B, String, String, u64, String>,
570    {
571        if m_a.f1.is_some() {
572            return MyCustomEffectType5 {
573                value: f(m_a.value).value, // Need a value of type B
574                f1: m_a.f1,
575                f2: m_a.f2,
576                f3: m_a.f3,
577                f4: m_a.f4,
578            };
579        }
580        let mut next_effect = f(m_a.value);
581
582        let mut combined_f2 = m_a.f2;
583        combined_f2.extend(next_effect.f2);
584        next_effect.f2 = combined_f2;
585
586        let mut combined_f3 = m_a.f3;
587        combined_f3.extend(next_effect.f3);
588        next_effect.f3 = combined_f3;
589
590        let mut combined_f4 = m_a.f4;
591        combined_f4.extend(next_effect.f4);
592        next_effect.f4 = combined_f4;
593
594        next_effect
595    }
596}
597
598/// A concrete implementation of `MonadEffect5` for testing purposes.
599///
600/// This struct provides the `pure` and `bind` operations for `MyEffect5`,
601/// demonstrating how monadic operations work with the arity 5 effect system.
602pub struct MyMonadEffect5;
603
604impl MonadEffect5<MyEffect5> for MyMonadEffect5 {
605    fn pure<T>(
606        value: T,
607    ) -> <<MyEffect5 as Effect5>::HktWitness as HKT5<
608        <MyEffect5 as Effect5>::Fixed1,
609        <MyEffect5 as Effect5>::Fixed2,
610        <MyEffect5 as Effect5>::Fixed3,
611        <MyEffect5 as Effect5>::Fixed4,
612    >>::Type<T> {
613        <MyEffect5 as Effect5>::HktWitness::pure(value)
614    }
615
616    fn bind<T, U, Func>(
617        effect: <<MyEffect5 as Effect5>::HktWitness as HKT5<
618            <MyEffect5 as Effect5>::Fixed1,
619            <MyEffect5 as Effect5>::Fixed2,
620            <MyEffect5 as Effect5>::Fixed3,
621            <MyEffect5 as Effect5>::Fixed4,
622        >>::Type<T>,
623        f: Func,
624    ) -> <<MyEffect5 as Effect5>::HktWitness as HKT5<
625        <MyEffect5 as Effect5>::Fixed1,
626        <MyEffect5 as Effect5>::Fixed2,
627        <MyEffect5 as Effect5>::Fixed3,
628        <MyEffect5 as Effect5>::Fixed4,
629    >>::Type<U>
630    where
631        Func: FnMut(
632            T,
633        ) -> <<MyEffect5 as Effect5>::HktWitness as HKT5<
634            <MyEffect5 as Effect5>::Fixed1,
635            <MyEffect5 as Effect5>::Fixed2,
636            <MyEffect5 as Effect5>::Fixed3,
637            <MyEffect5 as Effect5>::Fixed4,
638        >>::Type<U>,
639    {
640        <MyEffect5 as Effect5>::HktWitness::bind(effect, f)
641    }
642}
643
644/// A trait for adding log functionality to an arity 5 effect system.
645///
646/// This trait extends `MonadEffect5` by providing a `log` method,
647/// allowing for the accumulation of trace messages within the effect.
648pub trait LoggableEffect5<E: Effect5>: MonadEffect5<E>
649where
650    E::HktWitness: Functor<E::HktWitness> + Sized,
651{
652    /// Adds a log message (trace) to the effect's `f4` field.
653    ///
654    /// # Arguments
655    ///
656    /// *   `effect`: The effect to add the log message to.
657    /// *   `log`: The log message (trace string) to add.
658    ///
659    /// # Returns
660    ///
661    /// The modified effect with the log message appended.
662    #[allow(clippy::type_complexity)]
663    fn log<T>(
664        effect: <E::HktWitness as HKT5<E::Fixed1, E::Fixed2, E::Fixed3, E::Fixed4>>::Type<T>,
665        log: E::Fixed4,
666    ) -> <E::HktWitness as HKT5<E::Fixed1, E::Fixed2, E::Fixed3, E::Fixed4>>::Type<T>;
667}
668
669impl LoggableEffect5<MyEffect5> for MyMonadEffect5 {
670    #[allow(clippy::type_complexity)]
671    fn log<T>(
672        mut effect: <<MyEffect5 as Effect5>::HktWitness as HKT5<
673            <MyEffect5 as Effect5>::Fixed1,
674            <MyEffect5 as Effect5>::Fixed2,
675            <MyEffect5 as Effect5>::Fixed3,
676            <MyEffect5 as Effect5>::Fixed4,
677        >>::Type<T>,
678        log: <MyEffect5 as Effect5>::Fixed4,
679    ) -> <<MyEffect5 as Effect5>::HktWitness as HKT5<
680        <MyEffect5 as Effect5>::Fixed1,
681        <MyEffect5 as Effect5>::Fixed2,
682        <MyEffect5 as Effect5>::Fixed3,
683        <MyEffect5 as Effect5>::Fixed4,
684    >>::Type<T> {
685        effect.f4.push(log);
686        effect
687    }
688}