Skip to main content

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