Skip to main content

cgp_monad/monadic/
err.rs

1use cgp_core::prelude::*;
2use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent};
3
4use crate::monadic::ident::IdentMonadic;
5use crate::traits::{ContainsValue, LiftValue, MonadicBind, MonadicTrans};
6
7pub struct ErrMonadic;
8
9pub struct ErrMonadicTrans<M>(pub PhantomData<M>);
10
11impl<M> MonadicTrans<M> for ErrMonadic {
12    type M = ErrMonadicTrans<M>;
13}
14
15impl<M1, M2, M3> MonadicTrans<M2> for ErrMonadicTrans<M1>
16where
17    M1: MonadicTrans<M2, M = M3>,
18{
19    type M = ErrMonadicTrans<M3>;
20}
21
22impl<M, Provider> MonadicBind<Provider> for ErrMonadicTrans<M>
23where
24    M: MonadicBind<BindErr<M, Provider>>,
25{
26    type Provider = M::Provider;
27}
28
29impl<Provider> MonadicBind<Provider> for ErrMonadic {
30    type Provider = BindErr<IdentMonadic, Provider>;
31}
32pub struct BindErr<M, Cont>(pub PhantomData<(M, Cont)>);
33
34impl<T, E> ContainsValue<Result<T, E>> for ErrMonadic {
35    type Value = T;
36}
37
38impl<T, E> LiftValue<T, Result<T, E>> for ErrMonadic {
39    type Output = Result<T, E>;
40
41    fn lift_value(value: T) -> Self::Output {
42        Ok(value)
43    }
44
45    fn lift_output(output: Result<T, E>) -> Self::Output {
46        output
47    }
48}
49
50impl<T, E, V, M> ContainsValue<V> for ErrMonadicTrans<M>
51where
52    M: ContainsValue<V, Value = Result<T, E>>,
53{
54    type Value = T;
55}
56
57impl<T, E, V, M> LiftValue<T, V> for ErrMonadicTrans<M>
58where
59    M: ContainsValue<V, Value = Result<T, E>> + LiftValue<Result<T, E>, V>,
60{
61    type Output = M::Output;
62
63    fn lift_value(value: T) -> Self::Output {
64        M::lift_value(Ok(value))
65    }
66
67    fn lift_output(output: V) -> Self::Output {
68        M::lift_output(output)
69    }
70}
71
72#[cgp_provider]
73impl<Context, Code, T1, T2, E, M, Cont> Computer<Context, Code, Result<T1, E>> for BindErr<M, Cont>
74where
75    Cont: Computer<Context, Code, T1>,
76    M: ContainsValue<Cont::Output, Value = Result<T2, E>> + LiftValue<Result<T2, E>, Cont::Output>,
77{
78    type Output = M::Output;
79
80    fn compute(context: &Context, code: PhantomData<Code>, input: Result<T1, E>) -> Self::Output {
81        match input {
82            Ok(value) => M::lift_output(Cont::compute(context, code, value)),
83            Err(err) => M::lift_value(Err(err)),
84        }
85    }
86}
87
88#[cgp_provider]
89impl<Context, Code, T1, T2, E, M, Cont> AsyncComputer<Context, Code, Result<T1, E>>
90    for BindErr<M, Cont>
91where
92    Cont: AsyncComputer<Context, Code, T1>,
93    M: ContainsValue<Cont::Output, Value = Result<T2, E>> + LiftValue<Result<T2, E>, Cont::Output>,
94{
95    type Output = M::Output;
96
97    async fn compute_async(
98        context: &Context,
99        code: PhantomData<Code>,
100        input: Result<T1, E>,
101    ) -> Self::Output {
102        match input {
103            Ok(value) => M::lift_output(Cont::compute_async(context, code, value).await),
104            Err(err) => M::lift_value(Err(err)),
105        }
106    }
107}