From 246bca0b3bf4d77989a218eb61589b23e2bae004 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 16 Jul 2025 09:09:00 +0000 Subject: [PATCH 01/20] Add more shape examples --- crates/cgp-tests/src/tests/extractor/shape.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/crates/cgp-tests/src/tests/extractor/shape.rs b/crates/cgp-tests/src/tests/extractor/shape.rs index 64b91ef0..80af62ca 100644 --- a/crates/cgp-tests/src/tests/extractor/shape.rs +++ b/crates/cgp-tests/src/tests/extractor/shape.rs @@ -1,6 +1,8 @@ use std::f64::consts::PI; use cgp::core::field::{CanDowncast, CanDowncastFields, CanUpcast}; +use cgp::extra::dispatch::{ExtractFieldAndHandle, MatchWithHandlers}; +use cgp::extra::handler::HandleFieldValue; use cgp::prelude::*; #[derive(Debug, PartialEq, HasFields, FromVariant, ExtractField)] @@ -86,3 +88,42 @@ fn test_shape_downcast() { }, }; } + +pub trait HasArea { + fn area(self) -> f64; +} + +#[cgp_computer] +fn compute_area(shape: T) -> f64 { + shape.area() +} + +impl HasArea for Circle { + fn area(self) -> f64 { + PI * self.radius * self.radius + } +} + +impl HasArea for Rectangle { + fn area(self) -> f64 { + self.width * self.height + } +} + +impl HasArea for Triangle { + fn area(self) -> f64 { + self.base * self.height / 2.0 + } +} + +#[test] +fn test_match_with_handlers() { + let circle = Shape::Circle(Circle { radius: 5.0 }); + + let _area = MatchWithHandlers::< + Product![ + ExtractFieldAndHandle>, + ExtractFieldAndHandle>, + ], + >::compute(&(), PhantomData::<()>, circle); +} From abc3df00efdf10d4fa09867c0c8e692113bbb055 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 16 Jul 2025 09:18:26 +0000 Subject: [PATCH 02/20] Implement monadic bind implementation for BindOk and BindErr --- crates/cgp-monad/src/monadic/err.rs | 21 ++++++++++++++++++++- crates/cgp-monad/src/monadic/ok.rs | 21 ++++++++++++++++++++- crates/cgp-monad/src/traits/bind.rs | 7 +++++++ crates/cgp-monad/src/traits/mod.rs | 4 ++++ crates/cgp-monad/src/traits/value.rs | 3 +++ 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 crates/cgp-monad/src/traits/bind.rs create mode 100644 crates/cgp-monad/src/traits/value.rs diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 59af1bb4..ca09ba15 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -3,7 +3,7 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::Compose; +use crate::traits::{Compose, ContainsValue, MonadicLift}; pub struct ErrMonadic; @@ -13,6 +13,25 @@ impl Compose for ErrMonadic { pub struct ComposeErr(pub PhantomData<(ProviderA, ProviderB)>); +pub struct BindErr(pub PhantomData<(M, Cont)>); + +#[cgp_provider] +impl Computer> for BindErr +where + Cont: Computer, + M: ContainsValue> + + MonadicLift, Cont::Output>, +{ + type Output = M::Output; + + fn compute(context: &Context, code: PhantomData, input: Result) -> Self::Output { + match input { + Ok(value) => M::lift_output(Cont::compute(context, code, value)), + Err(err) => M::lift_value(Err(err)), + } + } +} + #[cgp_provider] impl Computer for ComposeErr diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 75cc1713..55594225 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -3,7 +3,7 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::Compose; +use crate::traits::{Compose, ContainsValue, MonadicLift}; pub struct OkMonadic; @@ -13,6 +13,25 @@ impl Compose for OkMonadic { pub struct ComposeOk(pub PhantomData<(ProviderA, ProviderB)>); +pub struct BindOk(pub PhantomData<(M, Cont)>); + +#[cgp_provider] +impl Computer> for BindOk +where + Cont: Computer, + M: ContainsValue> + + MonadicLift, Cont::Output>, +{ + type Output = M::Output; + + fn compute(context: &Context, code: PhantomData, input: Result) -> Self::Output { + match input { + Err(value) => M::lift_output(Cont::compute(context, code, value)), + Ok(err) => M::lift_value(Ok(err)), + } + } +} + #[cgp_provider] impl Computer for ComposeOk diff --git a/crates/cgp-monad/src/traits/bind.rs b/crates/cgp-monad/src/traits/bind.rs new file mode 100644 index 00000000..65f0faef --- /dev/null +++ b/crates/cgp-monad/src/traits/bind.rs @@ -0,0 +1,7 @@ +pub trait MonadicLift { + type Output; + + fn lift_value(value: Value) -> Self::Output; + + fn lift_output(output: Output) -> Self::Output; +} diff --git a/crates/cgp-monad/src/traits/mod.rs b/crates/cgp-monad/src/traits/mod.rs index 99ad4a53..30b89f0c 100644 --- a/crates/cgp-monad/src/traits/mod.rs +++ b/crates/cgp-monad/src/traits/mod.rs @@ -1,3 +1,7 @@ +mod bind; mod compose; +mod value; +pub use bind::*; pub use compose::*; +pub use value::*; diff --git a/crates/cgp-monad/src/traits/value.rs b/crates/cgp-monad/src/traits/value.rs new file mode 100644 index 00000000..dd897fb1 --- /dev/null +++ b/crates/cgp-monad/src/traits/value.rs @@ -0,0 +1,3 @@ +pub trait ContainsValue { + type Value; +} From 74759644378b2874a068d7f60af489062cd7b7c7 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 16 Jul 2025 09:24:07 +0000 Subject: [PATCH 03/20] Implement MonadicBind --- crates/cgp-monad/src/monadic/err.rs | 8 +++++++- crates/cgp-monad/src/monadic/ident.rs | 18 +++++++++++++++++- crates/cgp-monad/src/monadic/ok.rs | 8 +++++++- crates/cgp-monad/src/traits/bind.rs | 8 ++------ crates/cgp-monad/src/traits/lift.rs | 7 +++++++ crates/cgp-monad/src/traits/mod.rs | 2 ++ 6 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 crates/cgp-monad/src/traits/lift.rs diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index ca09ba15..999fc9e2 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -3,10 +3,16 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::{Compose, ContainsValue, MonadicLift}; +use crate::traits::{Compose, ContainsValue, MonadicBind, MonadicLift}; pub struct ErrMonadic; +pub struct ErrMonadicTrans(pub PhantomData); + +impl MonadicBind for ErrMonadicTrans { + type Provider = BindErr; +} + impl Compose for ErrMonadic { type Provider = ComposeErr; } diff --git a/crates/cgp-monad/src/monadic/ident.rs b/crates/cgp-monad/src/monadic/ident.rs index 0f64701f..6e276bf2 100644 --- a/crates/cgp-monad/src/monadic/ident.rs +++ b/crates/cgp-monad/src/monadic/ident.rs @@ -3,7 +3,7 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::Compose; +use crate::traits::{Compose, ContainsValue, MonadicLift}; pub struct IdentMonadic; @@ -13,6 +13,22 @@ impl Compose for IdentMonadic { pub struct ComposeIdent(pub PhantomData<(ProviderA, ProviderB)>); +impl ContainsValue for IdentMonadic { + type Value = T; +} + +impl MonadicLift for IdentMonadic { + type Output = T; + + fn lift_value(value: T) -> T { + value + } + + fn lift_output(value: T) -> T { + value + } +} + #[cgp_provider] impl Computer for ComposeIdent diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 55594225..3ea81ea4 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -3,10 +3,16 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::{Compose, ContainsValue, MonadicLift}; +use crate::traits::{Compose, ContainsValue, MonadicBind, MonadicLift}; pub struct OkMonadic; +pub struct OkMonadicTrans(pub PhantomData); + +impl MonadicBind for OkMonadicTrans { + type Provider = BindOk; +} + impl Compose for OkMonadic { type Provider = ComposeOk; } diff --git a/crates/cgp-monad/src/traits/bind.rs b/crates/cgp-monad/src/traits/bind.rs index 65f0faef..d5a401ca 100644 --- a/crates/cgp-monad/src/traits/bind.rs +++ b/crates/cgp-monad/src/traits/bind.rs @@ -1,7 +1,3 @@ -pub trait MonadicLift { - type Output; - - fn lift_value(value: Value) -> Self::Output; - - fn lift_output(output: Output) -> Self::Output; +pub trait MonadicBind { + type Provider; } diff --git a/crates/cgp-monad/src/traits/lift.rs b/crates/cgp-monad/src/traits/lift.rs new file mode 100644 index 00000000..65f0faef --- /dev/null +++ b/crates/cgp-monad/src/traits/lift.rs @@ -0,0 +1,7 @@ +pub trait MonadicLift { + type Output; + + fn lift_value(value: Value) -> Self::Output; + + fn lift_output(output: Output) -> Self::Output; +} diff --git a/crates/cgp-monad/src/traits/mod.rs b/crates/cgp-monad/src/traits/mod.rs index 30b89f0c..cb373540 100644 --- a/crates/cgp-monad/src/traits/mod.rs +++ b/crates/cgp-monad/src/traits/mod.rs @@ -1,7 +1,9 @@ mod bind; mod compose; +mod lift; mod value; pub use bind::*; pub use compose::*; +pub use lift::*; pub use value::*; From 4e463b148ab273c1f6cfbcf52788473fec7ff402 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 16 Jul 2025 09:27:33 +0000 Subject: [PATCH 04/20] Test use of BindErr --- crates/cgp-tests/src/tests/monad/err.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/cgp-tests/src/tests/monad/err.rs b/crates/cgp-tests/src/tests/monad/err.rs index d0ad05d6..57dd0687 100644 --- a/crates/cgp-tests/src/tests/monad/err.rs +++ b/crates/cgp-tests/src/tests/monad/err.rs @@ -1,4 +1,6 @@ -use cgp::extra::monad::monadic::err::{ComposeErr, ErrMonadic}; +use cgp::extra::handler::PipeHandlers; +use cgp::extra::monad::monadic::err::{BindErr, ComposeErr, ErrMonadic}; +use cgp::extra::monad::monadic::ident::IdentMonadic; use cgp::extra::monad::providers::PipeMonadic; use cgp::prelude::*; @@ -15,6 +17,20 @@ fn test_increment() { assert_eq!(Increment::compute(&context, code, 1), Ok(2)); assert_eq!(Increment::compute(&context, code, 255), Err("overflow")); + assert_eq!( + PipeHandlers::]>::compute( + &context, code, 1, + ), + Ok(3), + ); + + assert_eq!( + PipeHandlers::]>::compute( + &context, code, 254, + ), + Err("overflow"), + ); + assert_eq!( ComposeErr::::compute(&context, code, 1), Ok(3), From 6700f7fa696202eed2daea67841c4149b3fcb588 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 16 Jul 2025 09:32:46 +0000 Subject: [PATCH 05/20] Use MonadicBind in PipeMonadic --- crates/cgp-monad/src/monadic/err.rs | 9 ++++++++- crates/cgp-monad/src/monadic/ok.rs | 9 ++++++++- crates/cgp-monad/src/providers/pipe_monadic.rs | 10 ++++++---- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 999fc9e2..7ee6ebe9 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -3,7 +3,10 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::{Compose, ContainsValue, MonadicBind, MonadicLift}; +use crate::{ + monadic::ident::IdentMonadic, + traits::{Compose, ContainsValue, MonadicBind, MonadicLift}, +}; pub struct ErrMonadic; @@ -13,6 +16,10 @@ impl MonadicBind for ErrMonadicTrans { type Provider = BindErr; } +impl MonadicBind for ErrMonadic { + type Provider = BindErr; +} + impl Compose for ErrMonadic { type Provider = ComposeErr; } diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 3ea81ea4..743f3e11 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -3,7 +3,10 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::{Compose, ContainsValue, MonadicBind, MonadicLift}; +use crate::{ + monadic::ident::IdentMonadic, + traits::{Compose, ContainsValue, MonadicBind, MonadicLift}, +}; pub struct OkMonadic; @@ -13,6 +16,10 @@ impl MonadicBind for OkMonadicTrans { type Provider = BindOk; } +impl MonadicBind for OkMonadic { + type Provider = BindOk; +} + impl Compose for OkMonadic { type Provider = ComposeOk; } diff --git a/crates/cgp-monad/src/providers/pipe_monadic.rs b/crates/cgp-monad/src/providers/pipe_monadic.rs index b40fa7ae..8c07d679 100644 --- a/crates/cgp-monad/src/providers/pipe_monadic.rs +++ b/crates/cgp-monad/src/providers/pipe_monadic.rs @@ -3,7 +3,7 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::Compose; +use crate::traits::{Compose, MonadicBind}; pub struct PipeMonadic(pub PhantomData<(M, Providers)>); @@ -65,13 +65,15 @@ trait PipeComputer { impl PipeComputer for Cons> where - M: Compose>, Provider = OutProvider>, - OutProvider: Computer, + M: MonadicBind>, Provider = OutProvider>, + ProviderA: Computer, + OutProvider: Computer, { type Output = OutProvider::Output; fn compute(context: &Context, input: Input) -> Self::Output { - OutProvider::compute(context, PhantomData, input) + let intermediary = ProviderA::compute(context, PhantomData, input); + OutProvider::compute(context, PhantomData, intermediary) } } From c4d7e1cf9f359be9b64736f67901397694a26dca Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 08:10:46 +0000 Subject: [PATCH 06/20] Implement TryComputer for BindErr and BindOk --- crates/cgp-monad/src/monadic/err.rs | 24 ++++++++++++++++++++---- crates/cgp-monad/src/monadic/ok.rs | 24 ++++++++++++++++++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 7ee6ebe9..264d3b8e 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -3,10 +3,8 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::{ - monadic::ident::IdentMonadic, - traits::{Compose, ContainsValue, MonadicBind, MonadicLift}, -}; +use crate::monadic::ident::IdentMonadic; +use crate::traits::{Compose, ContainsValue, MonadicBind, MonadicLift}; pub struct ErrMonadic; @@ -45,6 +43,24 @@ where } } +#[cgp_provider] +impl TryComputer> for BindErr +where + Context: HasErrorType, + Cont: TryComputer, + M: ContainsValue> + + MonadicLift, Cont::Output>, +{ + type Output = M::Output; + + fn try_compute(context: &Context, code: PhantomData, input: Result) -> Result { + match input { + Ok(value) => Ok(M::lift_output(Cont::try_compute(context, code, value)?)), + Err(err) => Ok(M::lift_value(Err(err))), + } + } +} + #[cgp_provider] impl Computer for ComposeErr diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 743f3e11..25781b8e 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -3,10 +3,8 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::{ - monadic::ident::IdentMonadic, - traits::{Compose, ContainsValue, MonadicBind, MonadicLift}, -}; +use crate::monadic::ident::IdentMonadic; +use crate::traits::{Compose, ContainsValue, MonadicBind, MonadicLift}; pub struct OkMonadic; @@ -45,6 +43,24 @@ where } } +#[cgp_provider] +impl TryComputer> for BindOk +where + Context: HasErrorType, + Cont: TryComputer, + M: ContainsValue> + + MonadicLift, Cont::Output>, +{ + type Output = M::Output; + + fn try_compute(context: &Context, code: PhantomData, input: Result) -> Result { + match input { + Err(value) => Ok(M::lift_output(Cont::try_compute(context, code, value)?)), + Ok(err) => Ok(M::lift_value(Ok(err))), + } + } +} + #[cgp_provider] impl Computer for ComposeOk From 60ab7772cd2ffd2ad1ff4a9d9c2b625c3694c212 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 08:12:23 +0000 Subject: [PATCH 07/20] Use MonadicBind for PipeTryComputer --- crates/cgp-monad/src/providers/pipe_monadic.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/cgp-monad/src/providers/pipe_monadic.rs b/crates/cgp-monad/src/providers/pipe_monadic.rs index 8c07d679..4d14e7a2 100644 --- a/crates/cgp-monad/src/providers/pipe_monadic.rs +++ b/crates/cgp-monad/src/providers/pipe_monadic.rs @@ -102,13 +102,15 @@ impl PipeTryComputer for Cons> where Context: HasErrorType, - M: Compose>, Provider = OutProvider>, - OutProvider: TryComputer, + M: MonadicBind>, Provider = OutProvider>, + ProviderA: TryComputer, + OutProvider: TryComputer, { type Output = OutProvider::Output; fn try_compute(context: &Context, input: Input) -> Result { - OutProvider::try_compute(context, PhantomData, input) + let intermediary = ProviderA::try_compute(context, PhantomData, input)?; + OutProvider::try_compute(context, PhantomData, intermediary) } } From 587125763fa4e28e9539f8bd6270a87561bf3fad Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 08:15:33 +0000 Subject: [PATCH 08/20] Use MonadicBind for Handler --- crates/cgp-monad/src/monadic/err.rs | 18 ++++++++++++++++++ crates/cgp-monad/src/monadic/ok.rs | 18 ++++++++++++++++++ crates/cgp-monad/src/providers/pipe_monadic.rs | 10 ++++++---- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 264d3b8e..23a1109a 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -61,6 +61,24 @@ where } } +#[cgp_provider] +impl Handler> for BindErr +where + Context: HasAsyncErrorType, + Cont: Handler, + M: ContainsValue> + + MonadicLift, Cont::Output>, +{ + type Output = M::Output; + + async fn handle(context: &Context, code: PhantomData, input: Result) -> Result { + match input { + Ok(value) => Ok(M::lift_output(Cont::handle(context, code, value).await?)), + Err(err) => Ok(M::lift_value(Err(err))), + } + } +} + #[cgp_provider] impl Computer for ComposeErr diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 25781b8e..c8ad2c6b 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -61,6 +61,24 @@ where } } +#[cgp_provider] +impl Handler> for BindOk +where + Context: HasAsyncErrorType, + Cont: Handler, + M: ContainsValue> + + MonadicLift, Cont::Output>, +{ + type Output = M::Output; + + async fn handle(context: &Context, code: PhantomData, input: Result) -> Result { + match input { + Err(value) => Ok(M::lift_output(Cont::handle(context, code, value).await?)), + Ok(err) => Ok(M::lift_value(Ok(err))), + } + } +} + #[cgp_provider] impl Computer for ComposeOk diff --git a/crates/cgp-monad/src/providers/pipe_monadic.rs b/crates/cgp-monad/src/providers/pipe_monadic.rs index 4d14e7a2..1cca1ce2 100644 --- a/crates/cgp-monad/src/providers/pipe_monadic.rs +++ b/crates/cgp-monad/src/providers/pipe_monadic.rs @@ -3,7 +3,7 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::{Compose, MonadicBind}; +use crate::traits::MonadicBind; pub struct PipeMonadic(pub PhantomData<(M, Providers)>); @@ -144,13 +144,15 @@ impl for Cons> where Context: HasAsyncErrorType, - M: Compose>, Provider = OutProvider>, - OutProvider: Handler, + M: MonadicBind>, Provider = OutProvider>, + ProviderA: Handler, + OutProvider: Handler, { type Output = OutProvider::Output; async fn handle(context: &Context, input: Input) -> Result { - OutProvider::handle(context, PhantomData, input).await + let intermediary = ProviderA::handle(context, PhantomData, input).await?; + OutProvider::handle(context, PhantomData, intermediary).await } } From 542a8502f859b60496d5f86a871c15633d844c3d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 08:20:01 +0000 Subject: [PATCH 09/20] Remove old compose constructs --- crates/cgp-monad/src/monadic/err.rs | 89 ++++--------------------- crates/cgp-monad/src/monadic/ident.rs | 57 +--------------- crates/cgp-monad/src/monadic/ok.rs | 88 ++++-------------------- crates/cgp-monad/src/traits/compose.rs | 3 - crates/cgp-monad/src/traits/mod.rs | 2 - crates/cgp-tests/src/tests/monad/err.rs | 12 +--- 6 files changed, 30 insertions(+), 221 deletions(-) delete mode 100644 crates/cgp-monad/src/traits/compose.rs diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 23a1109a..e17200ce 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -4,7 +4,7 @@ use cgp_handler::{ }; use crate::monadic::ident::IdentMonadic; -use crate::traits::{Compose, ContainsValue, MonadicBind, MonadicLift}; +use crate::traits::{ContainsValue, MonadicBind, MonadicLift}; pub struct ErrMonadic; @@ -17,13 +17,6 @@ impl MonadicBind for ErrMonadicTrans { impl MonadicBind for ErrMonadic { type Provider = BindErr; } - -impl Compose for ErrMonadic { - type Provider = ComposeErr; -} - -pub struct ComposeErr(pub PhantomData<(ProviderA, ProviderB)>); - pub struct BindErr(pub PhantomData<(M, Cont)>); #[cgp_provider] @@ -44,7 +37,8 @@ where } #[cgp_provider] -impl TryComputer> for BindErr +impl TryComputer> + for BindErr where Context: HasErrorType, Cont: TryComputer, @@ -53,7 +47,11 @@ where { type Output = M::Output; - fn try_compute(context: &Context, code: PhantomData, input: Result) -> Result { + fn try_compute( + context: &Context, + code: PhantomData, + input: Result, + ) -> Result { match input { Ok(value) => Ok(M::lift_output(Cont::try_compute(context, code, value)?)), Err(err) => Ok(M::lift_value(Err(err))), @@ -62,7 +60,8 @@ where } #[cgp_provider] -impl Handler> for BindErr +impl Handler> + for BindErr where Context: HasAsyncErrorType, Cont: Handler, @@ -71,74 +70,14 @@ where { type Output = M::Output; - async fn handle(context: &Context, code: PhantomData, input: Result) -> Result { - match input { - Ok(value) => Ok(M::lift_output(Cont::handle(context, code, value).await?)), - Err(err) => Ok(M::lift_value(Err(err))), - } - } -} - -#[cgp_provider] -impl Computer - for ComposeErr -where - ProviderA: Computer>, - ProviderB: Computer>, -{ - type Output = Result; - - fn compute(context: &Context, code: PhantomData, input: Input) -> Self::Output { - let res = ProviderA::compute(context, code, input); - match res { - Ok(value) => ProviderB::compute(context, code, value), - Err(err) => Err(err), - } - } -} - -#[cgp_provider] -impl TryComputer - for ComposeErr -where - Context: HasErrorType, - ProviderA: TryComputer>, - ProviderB: TryComputer>, -{ - type Output = Result; - - fn try_compute( - context: &Context, - code: PhantomData, - input: Input, - ) -> Result { - let res = ProviderA::try_compute(context, code, input)?; - match res { - Ok(value) => ProviderB::try_compute(context, code, value), - Err(err) => Ok(Err(err)), - } - } -} - -#[cgp_provider] -impl - Handler for ComposeErr -where - Context: HasAsyncErrorType, - ProviderA: Handler>, - ProviderB: Handler>, -{ - type Output = Result; - async fn handle( context: &Context, code: PhantomData, - input: Input, + input: Result, ) -> Result { - let res = ProviderA::handle(context, code, input).await?; - match res { - Ok(value) => ProviderB::handle(context, code, value).await, - Err(err) => Ok(Err(err)), + match input { + Ok(value) => Ok(M::lift_output(Cont::handle(context, code, value).await?)), + Err(err) => Ok(M::lift_value(Err(err))), } } } diff --git a/crates/cgp-monad/src/monadic/ident.rs b/crates/cgp-monad/src/monadic/ident.rs index 6e276bf2..36693e09 100644 --- a/crates/cgp-monad/src/monadic/ident.rs +++ b/crates/cgp-monad/src/monadic/ident.rs @@ -3,7 +3,7 @@ use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::traits::{Compose, ContainsValue, MonadicLift}; +use crate::traits::{ContainsValue, MonadicLift}; pub struct IdentMonadic; @@ -28,58 +28,3 @@ impl MonadicLift for IdentMonadic { value } } - -#[cgp_provider] -impl Computer - for ComposeIdent -where - ProviderA: Computer, - ProviderB: Computer, -{ - type Output = ProviderB::Output; - - fn compute(context: &Context, code: PhantomData, input: Input) -> Self::Output { - let res = ProviderA::compute(context, code, input); - ProviderB::compute(context, code, res) - } -} - -#[cgp_provider] -impl TryComputer - for ComposeIdent -where - Context: HasErrorType, - ProviderA: TryComputer, - ProviderB: TryComputer, -{ - type Output = ProviderB::Output; - - fn try_compute( - context: &Context, - code: PhantomData, - input: Input, - ) -> Result { - let res = ProviderA::try_compute(context, code, input)?; - ProviderB::try_compute(context, code, res) - } -} - -#[cgp_provider] -impl Handler - for ComposeIdent -where - Context: HasAsyncErrorType, - ProviderA: Handler, - ProviderB: Handler, -{ - type Output = ProviderB::Output; - - async fn handle( - context: &Context, - code: PhantomData, - input: Input, - ) -> Result { - let res = ProviderA::handle(context, code, input).await?; - ProviderB::handle(context, code, res).await - } -} diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index c8ad2c6b..b1dc459b 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -4,7 +4,7 @@ use cgp_handler::{ }; use crate::monadic::ident::IdentMonadic; -use crate::traits::{Compose, ContainsValue, MonadicBind, MonadicLift}; +use crate::traits::{ContainsValue, MonadicBind, MonadicLift}; pub struct OkMonadic; @@ -18,12 +18,6 @@ impl MonadicBind for OkMonadic { type Provider = BindOk; } -impl Compose for OkMonadic { - type Provider = ComposeOk; -} - -pub struct ComposeOk(pub PhantomData<(ProviderA, ProviderB)>); - pub struct BindOk(pub PhantomData<(M, Cont)>); #[cgp_provider] @@ -44,7 +38,8 @@ where } #[cgp_provider] -impl TryComputer> for BindOk +impl TryComputer> + for BindOk where Context: HasErrorType, Cont: TryComputer, @@ -53,7 +48,11 @@ where { type Output = M::Output; - fn try_compute(context: &Context, code: PhantomData, input: Result) -> Result { + fn try_compute( + context: &Context, + code: PhantomData, + input: Result, + ) -> Result { match input { Err(value) => Ok(M::lift_output(Cont::try_compute(context, code, value)?)), Ok(err) => Ok(M::lift_value(Ok(err))), @@ -62,7 +61,8 @@ where } #[cgp_provider] -impl Handler> for BindOk +impl + Handler> for BindOk where Context: HasAsyncErrorType, Cont: Handler, @@ -71,74 +71,14 @@ where { type Output = M::Output; - async fn handle(context: &Context, code: PhantomData, input: Result) -> Result { - match input { - Err(value) => Ok(M::lift_output(Cont::handle(context, code, value).await?)), - Ok(err) => Ok(M::lift_value(Ok(err))), - } - } -} - -#[cgp_provider] -impl Computer - for ComposeOk -where - ProviderA: Computer>, - ProviderB: Computer>, -{ - type Output = Result; - - fn compute(context: &Context, code: PhantomData, input: Input) -> Self::Output { - let res = ProviderA::compute(context, code, input); - match res { - Err(value) => ProviderB::compute(context, code, value), - Ok(err) => Ok(err), - } - } -} - -#[cgp_provider] -impl TryComputer - for ComposeOk -where - Context: HasErrorType, - ProviderA: TryComputer>, - ProviderB: TryComputer>, -{ - type Output = Result; - - fn try_compute( - context: &Context, - code: PhantomData, - input: Input, - ) -> Result { - let res = ProviderA::try_compute(context, code, input)?; - match res { - Err(value) => ProviderB::try_compute(context, code, value), - Ok(err) => Ok(Ok(err)), - } - } -} - -#[cgp_provider] -impl - Handler for ComposeOk -where - Context: HasAsyncErrorType, - ProviderA: Handler>, - ProviderB: Handler>, -{ - type Output = Result; - async fn handle( context: &Context, code: PhantomData, - input: Input, + input: Result, ) -> Result { - let res = ProviderA::handle(context, code, input).await?; - match res { - Err(value) => ProviderB::handle(context, code, value).await, - Ok(err) => Ok(Ok(err)), + match input { + Err(value) => Ok(M::lift_output(Cont::handle(context, code, value).await?)), + Ok(err) => Ok(M::lift_value(Ok(err))), } } } diff --git a/crates/cgp-monad/src/traits/compose.rs b/crates/cgp-monad/src/traits/compose.rs deleted file mode 100644 index e6643d5f..00000000 --- a/crates/cgp-monad/src/traits/compose.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub trait Compose { - type Provider; -} diff --git a/crates/cgp-monad/src/traits/mod.rs b/crates/cgp-monad/src/traits/mod.rs index cb373540..c8afefee 100644 --- a/crates/cgp-monad/src/traits/mod.rs +++ b/crates/cgp-monad/src/traits/mod.rs @@ -1,9 +1,7 @@ mod bind; -mod compose; mod lift; mod value; pub use bind::*; -pub use compose::*; pub use lift::*; pub use value::*; diff --git a/crates/cgp-tests/src/tests/monad/err.rs b/crates/cgp-tests/src/tests/monad/err.rs index 57dd0687..c2748953 100644 --- a/crates/cgp-tests/src/tests/monad/err.rs +++ b/crates/cgp-tests/src/tests/monad/err.rs @@ -1,5 +1,5 @@ use cgp::extra::handler::PipeHandlers; -use cgp::extra::monad::monadic::err::{BindErr, ComposeErr, ErrMonadic}; +use cgp::extra::monad::monadic::err::{BindErr, ErrMonadic}; use cgp::extra::monad::monadic::ident::IdentMonadic; use cgp::extra::monad::providers::PipeMonadic; use cgp::prelude::*; @@ -31,16 +31,6 @@ fn test_increment() { Err("overflow"), ); - assert_eq!( - ComposeErr::::compute(&context, code, 1), - Ok(3), - ); - - assert_eq!( - ComposeErr::::compute(&context, code, 254), - Err("overflow"), - ); - assert_eq!( PipeMonadic::::compute(&context, code, 1), Ok(2), From fccf3f67c9055cad8175a73d0169c8eeff2f458d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 08:28:59 +0000 Subject: [PATCH 10/20] Implement value lifting for OkMonadic and ErrMonadic --- crates/cgp-monad/src/monadic/err.rs | 27 ++++++++++++++++++------- crates/cgp-monad/src/monadic/ident.rs | 15 ++++---------- crates/cgp-monad/src/monadic/ok.rs | 29 +++++++++++++++++++-------- crates/cgp-monad/src/traits/lift.rs | 2 +- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index e17200ce..5cbf4e2d 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -4,7 +4,7 @@ use cgp_handler::{ }; use crate::monadic::ident::IdentMonadic; -use crate::traits::{ContainsValue, MonadicBind, MonadicLift}; +use crate::traits::{ContainsValue, LiftValue, MonadicBind}; pub struct ErrMonadic; @@ -19,12 +19,27 @@ impl MonadicBind for ErrMonadic { } pub struct BindErr(pub PhantomData<(M, Cont)>); +impl ContainsValue> for ErrMonadic { + type Value = T; +} + +impl LiftValue> for ErrMonadic { + type Output = Result; + + fn lift_value(value: T) -> Self::Output { + Ok(value) + } + + fn lift_output(output: Result) -> Self::Output { + output + } +} + #[cgp_provider] impl Computer> for BindErr where Cont: Computer, - M: ContainsValue> - + MonadicLift, Cont::Output>, + M: ContainsValue> + LiftValue, Cont::Output>, { type Output = M::Output; @@ -42,8 +57,7 @@ impl TryComputer where Context: HasErrorType, Cont: TryComputer, - M: ContainsValue> - + MonadicLift, Cont::Output>, + M: ContainsValue> + LiftValue, Cont::Output>, { type Output = M::Output; @@ -65,8 +79,7 @@ impl Handler, - M: ContainsValue> - + MonadicLift, Cont::Output>, + M: ContainsValue> + LiftValue, Cont::Output>, { type Output = M::Output; diff --git a/crates/cgp-monad/src/monadic/ident.rs b/crates/cgp-monad/src/monadic/ident.rs index 36693e09..fb254c62 100644 --- a/crates/cgp-monad/src/monadic/ident.rs +++ b/crates/cgp-monad/src/monadic/ident.rs @@ -1,23 +1,16 @@ -use cgp_core::prelude::*; -use cgp_handler::{ - Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, -}; - -use crate::traits::{ContainsValue, MonadicLift}; +use crate::traits::{ContainsValue, LiftValue, MonadicBind}; pub struct IdentMonadic; -impl Compose for IdentMonadic { - type Provider = ComposeIdent; +impl MonadicBind for IdentMonadic { + type Provider = Provider; } -pub struct ComposeIdent(pub PhantomData<(ProviderA, ProviderB)>); - impl ContainsValue for IdentMonadic { type Value = T; } -impl MonadicLift for IdentMonadic { +impl LiftValue for IdentMonadic { type Output = T; fn lift_value(value: T) -> T { diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index b1dc459b..d41bd1f9 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -4,12 +4,14 @@ use cgp_handler::{ }; use crate::monadic::ident::IdentMonadic; -use crate::traits::{ContainsValue, MonadicBind, MonadicLift}; +use crate::traits::{ContainsValue, LiftValue, MonadicBind}; pub struct OkMonadic; pub struct OkMonadicTrans(pub PhantomData); +pub struct BindOk(pub PhantomData<(M, Cont)>); + impl MonadicBind for OkMonadicTrans { type Provider = BindOk; } @@ -18,14 +20,27 @@ impl MonadicBind for OkMonadic { type Provider = BindOk; } -pub struct BindOk(pub PhantomData<(M, Cont)>); +impl ContainsValue> for OkMonadic { + type Value = E; +} + +impl LiftValue> for OkMonadic { + type Output = Result; + + fn lift_value(value: E) -> Self::Output { + Err(value) + } + + fn lift_output(output: Result) -> Self::Output { + output + } +} #[cgp_provider] impl Computer> for BindOk where Cont: Computer, - M: ContainsValue> - + MonadicLift, Cont::Output>, + M: ContainsValue> + LiftValue, Cont::Output>, { type Output = M::Output; @@ -43,8 +58,7 @@ impl TryComputer where Context: HasErrorType, Cont: TryComputer, - M: ContainsValue> - + MonadicLift, Cont::Output>, + M: ContainsValue> + LiftValue, Cont::Output>, { type Output = M::Output; @@ -66,8 +80,7 @@ impl where Context: HasAsyncErrorType, Cont: Handler, - M: ContainsValue> - + MonadicLift, Cont::Output>, + M: ContainsValue> + LiftValue, Cont::Output>, { type Output = M::Output; diff --git a/crates/cgp-monad/src/traits/lift.rs b/crates/cgp-monad/src/traits/lift.rs index 65f0faef..f2f39d61 100644 --- a/crates/cgp-monad/src/traits/lift.rs +++ b/crates/cgp-monad/src/traits/lift.rs @@ -1,4 +1,4 @@ -pub trait MonadicLift { +pub trait LiftValue { type Output; fn lift_value(value: Value) -> Self::Output; From 2c37be4304337ba281222d0c8d4e4ee29df9094d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 08:47:05 +0000 Subject: [PATCH 11/20] Use BindProviders to simplify implementation of PipeMonadic --- crates/cgp-monad/src/providers/compose.rs | 61 +++++++ crates/cgp-monad/src/providers/mod.rs | 2 + .../cgp-monad/src/providers/pipe_monadic.rs | 171 ++---------------- 3 files changed, 77 insertions(+), 157 deletions(-) create mode 100644 crates/cgp-monad/src/providers/compose.rs diff --git a/crates/cgp-monad/src/providers/compose.rs b/crates/cgp-monad/src/providers/compose.rs new file mode 100644 index 00000000..682633e8 --- /dev/null +++ b/crates/cgp-monad/src/providers/compose.rs @@ -0,0 +1,61 @@ +use cgp_core::prelude::*; +use cgp_handler::{ + Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, +}; + +pub struct ComposeHandlers(pub PhantomData<(ProviderA, ProviderB)>); + +#[cgp_provider] +impl Computer + for ComposeHandlers +where + ProviderA: Computer, + ProviderB: Computer, +{ + type Output = ProviderB::Output; + + fn compute(context: &Context, code: PhantomData, input: Input) -> Self::Output { + let intermediary = ProviderA::compute(context, code, input); + ProviderB::compute(context, code, intermediary) + } +} + +#[cgp_provider] +impl TryComputer + for ComposeHandlers +where + Context: HasErrorType, + ProviderA: TryComputer, + ProviderB: TryComputer, +{ + type Output = ProviderB::Output; + + fn try_compute( + context: &Context, + code: PhantomData, + input: Input, + ) -> Result { + let intermediary = ProviderA::try_compute(context, code, input)?; + ProviderB::try_compute(context, code, intermediary) + } +} + +#[cgp_provider] +impl Handler + for ComposeHandlers +where + Context: HasAsyncErrorType, + ProviderA: Handler, + ProviderB: Handler, +{ + type Output = ProviderB::Output; + + async fn handle( + context: &Context, + code: PhantomData, + input: Input, + ) -> Result { + let intermediary = ProviderA::handle(context, code, input).await?; + ProviderB::handle(context, code, intermediary).await + } +} diff --git a/crates/cgp-monad/src/providers/mod.rs b/crates/cgp-monad/src/providers/mod.rs index 82315b89..4651f2f6 100644 --- a/crates/cgp-monad/src/providers/mod.rs +++ b/crates/cgp-monad/src/providers/mod.rs @@ -1,3 +1,5 @@ +mod compose; mod pipe_monadic; +pub use compose::*; pub use pipe_monadic::*; diff --git a/crates/cgp-monad/src/providers/pipe_monadic.rs b/crates/cgp-monad/src/providers/pipe_monadic.rs index 1cca1ce2..05ee2c1f 100644 --- a/crates/cgp-monad/src/providers/pipe_monadic.rs +++ b/crates/cgp-monad/src/providers/pipe_monadic.rs @@ -1,173 +1,30 @@ use cgp_core::prelude::*; -use cgp_handler::{ - Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, -}; +use crate::providers::ComposeHandlers; use crate::traits::MonadicBind; pub struct PipeMonadic(pub PhantomData<(M, Providers)>); -#[cgp_provider] -impl Computer - for PipeMonadic -where - Providers: PipeComputer, -{ - type Output = Output; - - fn compute(context: &Context, _code: PhantomData, input: Input) -> Self::Output { - Providers::compute(context, input) - } -} - -#[cgp_provider] -impl TryComputer - for PipeMonadic -where - Context: HasErrorType, - Providers: PipeTryComputer, -{ - type Output = Output; - - fn try_compute( - context: &Context, - _code: PhantomData, - input: Input, - ) -> Result { - Providers::try_compute(context, input) - } -} - -#[cgp_provider] -impl Handler - for PipeMonadic -where - Context: HasAsyncErrorType, - Providers: PipeHandler, -{ - type Output = Output; - - async fn handle( - context: &Context, - _code: PhantomData, - input: Input, - ) -> Result { - Providers::handle(context, input).await - } -} - -trait PipeComputer { - type Output; - - fn compute(context: &Context, input: Input) -> Self::Output; -} - -impl - PipeComputer for Cons> -where - M: MonadicBind>, Provider = OutProvider>, - ProviderA: Computer, - OutProvider: Computer, -{ - type Output = OutProvider::Output; - - fn compute(context: &Context, input: Input) -> Self::Output { - let intermediary = ProviderA::compute(context, PhantomData, input); - OutProvider::compute(context, PhantomData, intermediary) - } -} - -impl PipeComputer - for Cons -where - Provider: Computer, -{ - type Output = Provider::Output; - - fn compute(context: &Context, input: Input) -> Self::Output { - Provider::compute(context, PhantomData, input) - } -} - -trait PipeTryComputer -where - Context: HasErrorType, -{ - type Output; - - fn try_compute(context: &Context, input: Input) -> Result; -} - -impl - PipeTryComputer for Cons> -where - Context: HasErrorType, - M: MonadicBind>, Provider = OutProvider>, - ProviderA: TryComputer, - OutProvider: TryComputer, -{ - type Output = OutProvider::Output; - - fn try_compute(context: &Context, input: Input) -> Result { - let intermediary = ProviderA::try_compute(context, PhantomData, input)?; - OutProvider::try_compute(context, PhantomData, intermediary) - } -} - -impl PipeTryComputer - for Cons -where - Context: HasErrorType, - Provider: TryComputer, -{ - type Output = Provider::Output; - - fn try_compute( - context: &Context, - input: Input, - ) -> Result::Error> { - Provider::try_compute(context, PhantomData, input) +delegate_components! { + > + PipeMonadic { + Component: Provider, } } -#[async_trait] -trait PipeHandler -where - Context: HasAsyncErrorType, -{ - type Output; - - async fn handle(context: &Context, input: Input) -> Result; +trait BindProviders { + type Provider; } -impl - PipeHandler for Cons> +impl BindProviders + for Cons> where - Context: HasAsyncErrorType, - M: MonadicBind>, Provider = OutProvider>, - ProviderA: Handler, - OutProvider: Handler, + Cons: BindProviders, + M: MonadicBind, { - type Output = OutProvider::Output; - - async fn handle(context: &Context, input: Input) -> Result { - let intermediary = ProviderA::handle(context, PhantomData, input).await?; - OutProvider::handle(context, PhantomData, intermediary).await - } + type Provider = ComposeHandlers; } -impl PipeHandler - for Cons -where - Context: HasAsyncErrorType, - Provider: Handler, -{ - type Output = Provider::Output; - - async fn handle( - context: &Context, - input: Input, - ) -> Result::Error> { - Provider::handle(context, PhantomData, input).await - } +impl BindProviders for Cons { + type Provider = Provider; } From 8e43000122dce54841e2672fdaecf07ee1054082 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 08:52:05 +0000 Subject: [PATCH 12/20] Use ComposeHandlers in PipeHandlers --- .../src/providers/compose.rs | 3 +- crates/cgp-handler/src/providers/mod.rs | 2 + crates/cgp-handler/src/providers/pipe.rs | 183 ++---------------- crates/cgp-monad/src/providers/mod.rs | 2 - .../cgp-monad/src/providers/pipe_monadic.rs | 2 +- 5 files changed, 18 insertions(+), 174 deletions(-) rename crates/{cgp-monad => cgp-handler}/src/providers/compose.rs (99%) diff --git a/crates/cgp-monad/src/providers/compose.rs b/crates/cgp-handler/src/providers/compose.rs similarity index 99% rename from crates/cgp-monad/src/providers/compose.rs rename to crates/cgp-handler/src/providers/compose.rs index 682633e8..3fc2b219 100644 --- a/crates/cgp-monad/src/providers/compose.rs +++ b/crates/cgp-handler/src/providers/compose.rs @@ -1,5 +1,6 @@ use cgp_core::prelude::*; -use cgp_handler::{ + +use crate::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; diff --git a/crates/cgp-handler/src/providers/mod.rs b/crates/cgp-handler/src/providers/mod.rs index c95efb17..e86ac15e 100644 --- a/crates/cgp-handler/src/providers/mod.rs +++ b/crates/cgp-handler/src/providers/mod.rs @@ -1,9 +1,11 @@ +mod compose; mod field; mod pipe; mod promote; mod promote_ref; mod return_input; +pub use compose::*; pub use field::*; pub use pipe::*; pub use promote::*; diff --git a/crates/cgp-handler/src/providers/pipe.rs b/crates/cgp-handler/src/providers/pipe.rs index 188bdcd4..4a368b16 100644 --- a/crates/cgp-handler/src/providers/pipe.rs +++ b/crates/cgp-handler/src/providers/pipe.rs @@ -2,186 +2,29 @@ use core::marker::PhantomData; use cgp_core::prelude::*; -use crate::components::*; +use crate::ComposeHandlers; pub struct PipeHandlers(pub PhantomData); -#[cgp_provider] -impl Computer - for PipeHandlers -where - Providers: PipeComputer, -{ - type Output = Output; - - fn compute(context: &Context, tag: PhantomData, input: Input) -> Output { - Providers::compute(context, tag, input) - } -} - -#[cgp_provider] -impl TryComputer - for PipeHandlers -where - Context: HasErrorType, - Providers: PipeTryComputer, -{ - type Output = Output; - - fn try_compute( - context: &Context, - tag: PhantomData, - input: Input, - ) -> Result { - Providers::try_compute(context, tag, input) - } -} - -#[cgp_provider] -impl Handler - for PipeHandlers -where - Context: HasAsyncErrorType, - Providers: PipeHandler, - Code: Send, - Input: Send, - Output: Send, -{ - type Output = Output; - - async fn handle( - context: &Context, - tag: PhantomData, - input: Input, - ) -> Result { - Providers::handle(context, tag, input).await - } -} - -trait PipeComputer { - type Output; - - fn compute(context: &Context, _code: PhantomData, input: Input) -> Self::Output; -} - -impl PipeComputer - for Cons -where - CurrentProvider: Computer, - RestProviders: PipeComputer, -{ - type Output = Output; - - fn compute(context: &Context, tag: PhantomData, input: Input) -> Output { - let intermediate = CurrentProvider::compute(context, tag, input); - RestProviders::compute(context, tag, intermediate) - } -} - -impl PipeComputer for Nil { - type Output = Input; - - fn compute(_context: &Context, _code: PhantomData, input: Input) -> Input { - input +delegate_components! { + > + PipeHandlers { + Component: Provider, } } -trait PipeTryComputer -where - Context: HasErrorType, -{ - type Output; - - fn try_compute( - context: &Context, - _code: PhantomData, - input: Input, - ) -> Result; -} - -impl - PipeTryComputer for Cons -where - Context: HasErrorType, - CurrentProvider: TryComputer, - RestProviders: PipeTryComputer, -{ - type Output = Output; - - fn try_compute( - context: &Context, - tag: PhantomData, - input: Input, - ) -> Result { - let intermediate = CurrentProvider::try_compute(context, tag, input)?; - RestProviders::try_compute(context, tag, intermediate) - } +trait ComposeProviders { + type Provider; } -impl PipeTryComputer for Nil +impl ComposeProviders + for Cons> where - Context: HasErrorType, + Cons: ComposeProviders, { - type Output = Input; - - fn try_compute( - _context: &Context, - _code: PhantomData, - input: Input, - ) -> Result { - Ok(input) - } + type Provider = ComposeHandlers; } -#[async_trait] -trait PipeHandler -where - Context: HasAsyncErrorType, -{ - type Output; - - async fn handle( - context: &Context, - _code: PhantomData, - input: Input, - ) -> Result; -} - -impl PipeHandler - for Cons -where - Context: HasAsyncErrorType, - CurrentProvider: Handler, - RestProviders: PipeHandler, - Code: Send, - Input: Send, - Output: Send, -{ - type Output = Output; - - async fn handle( - context: &Context, - tag: PhantomData, - input: Input, - ) -> Result { - let intermediate = CurrentProvider::handle(context, tag, input).await?; - RestProviders::handle(context, tag, intermediate).await - } -} - -impl PipeHandler for Nil -where - Context: HasAsyncErrorType, - Code: Send, - Input: Send, -{ - type Output = Input; - - async fn handle( - _context: &Context, - _code: PhantomData, - input: Input, - ) -> Result { - Ok(input) - } +impl ComposeProviders for Cons { + type Provider = Provider; } diff --git a/crates/cgp-monad/src/providers/mod.rs b/crates/cgp-monad/src/providers/mod.rs index 4651f2f6..82315b89 100644 --- a/crates/cgp-monad/src/providers/mod.rs +++ b/crates/cgp-monad/src/providers/mod.rs @@ -1,5 +1,3 @@ -mod compose; mod pipe_monadic; -pub use compose::*; pub use pipe_monadic::*; diff --git a/crates/cgp-monad/src/providers/pipe_monadic.rs b/crates/cgp-monad/src/providers/pipe_monadic.rs index 05ee2c1f..2baadfbc 100644 --- a/crates/cgp-monad/src/providers/pipe_monadic.rs +++ b/crates/cgp-monad/src/providers/pipe_monadic.rs @@ -1,6 +1,6 @@ use cgp_core::prelude::*; +use cgp_handler::ComposeHandlers; -use crate::providers::ComposeHandlers; use crate::traits::MonadicBind; pub struct PipeMonadic(pub PhantomData<(M, Providers)>); From 561309d59f4cd76ca1c74ad5b93ff4963a695940 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 08:59:51 +0000 Subject: [PATCH 13/20] Implement TryPromote for Computer --- crates/cgp-handler/src/providers/mod.rs | 2 + crates/cgp-handler/src/providers/promote.rs | 42 --------------- .../cgp-handler/src/providers/try_promote.rs | 51 +++++++++++++++++++ 3 files changed, 53 insertions(+), 42 deletions(-) create mode 100644 crates/cgp-handler/src/providers/try_promote.rs diff --git a/crates/cgp-handler/src/providers/mod.rs b/crates/cgp-handler/src/providers/mod.rs index e86ac15e..2d44bb45 100644 --- a/crates/cgp-handler/src/providers/mod.rs +++ b/crates/cgp-handler/src/providers/mod.rs @@ -4,6 +4,7 @@ mod pipe; mod promote; mod promote_ref; mod return_input; +mod try_promote; pub use compose::*; pub use field::*; @@ -11,3 +12,4 @@ pub use pipe::*; pub use promote::*; pub use promote_ref::*; pub use return_input::*; +pub use try_promote::*; \ No newline at end of file diff --git a/crates/cgp-handler/src/providers/promote.rs b/crates/cgp-handler/src/providers/promote.rs index 2c28ec33..d6ba19ee 100644 --- a/crates/cgp-handler/src/providers/promote.rs +++ b/crates/cgp-handler/src/providers/promote.rs @@ -7,8 +7,6 @@ use crate::{ pub struct Promote(pub PhantomData); -pub struct TryPromote(pub PhantomData); - pub type Promote2 = Promote>; pub type Promote3 = Promote>; @@ -61,43 +59,3 @@ where Ok(Provider::compute(context, code, input)) } } - -#[cgp_provider] -impl Handler - for TryPromote -where - Context: CanRaiseAsyncError, - Provider: Computer>, - Code: Send, - Input: Send, - Output: Send, - Error: Send, -{ - type Output = Output; - - async fn handle( - context: &Context, - tag: PhantomData, - input: Input, - ) -> Result { - Provider::compute(context, tag, input).map_err(Context::raise_error) - } -} - -#[cgp_provider] -impl TryComputer - for TryPromote -where - Context: CanRaiseError, - Provider: Computer>, -{ - type Output = Output; - - fn try_compute( - context: &Context, - tag: PhantomData, - input: Input, - ) -> Result { - Provider::compute(context, tag, input).map_err(Context::raise_error) - } -} diff --git a/crates/cgp-handler/src/providers/try_promote.rs b/crates/cgp-handler/src/providers/try_promote.rs new file mode 100644 index 00000000..35d77255 --- /dev/null +++ b/crates/cgp-handler/src/providers/try_promote.rs @@ -0,0 +1,51 @@ +use cgp_core::prelude::*; + +use crate::{ + Computer, ComputerComponent, HandlerComponent, Promote, TryComputer, TryComputerComponent +}; + +pub struct TryPromote(pub PhantomData); + +delegate_components! { + + TryPromote { + HandlerComponent: Promote>, + } +} + +#[cgp_provider] +impl TryComputer + for TryPromote +where + Context: CanRaiseError, + Provider: Computer>, +{ + type Output = Output; + + fn try_compute( + context: &Context, + tag: PhantomData, + input: Input, + ) -> Result { + Provider::compute(context, tag, input).map_err(Context::raise_error) + } +} + + +#[cgp_provider] +impl Computer + for TryPromote +where + Context: HasErrorType, + Provider: TryComputer, +{ + type Output = Result; + + fn compute( + context: &Context, + tag: PhantomData, + input: Input, + ) -> Result { + Provider::try_compute(context, tag, input) + } +} From c7bcf32357799293e217a413a5da37004de89266 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 09:11:03 +0000 Subject: [PATCH 14/20] Implement LiftValue for ErrMonadicTrans --- crates/cgp-monad/src/monadic/err.rs | 22 ++++++++++++++++++++++ crates/cgp-monad/src/monadic/ok.rs | 11 ++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 5cbf4e2d..3c133a74 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -35,6 +35,28 @@ impl LiftValue> for ErrMonadic { } } +impl ContainsValue for ErrMonadicTrans +where + M: ContainsValue> +{ + type Value = T; +} + +impl LiftValue for ErrMonadicTrans +where + M: ContainsValue> + LiftValue, V>, +{ + type Output = M::Output; + + fn lift_value(value: T) -> Self::Output { + M::lift_value(Ok(value)) + } + + fn lift_output(output: V) -> Self::Output { + M::lift_output(output) + } +} + #[cgp_provider] impl Computer> for BindErr where diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index d41bd1f9..74eb6179 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -1,8 +1,9 @@ use cgp_core::prelude::*; use cgp_handler::{ - Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, + Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, TryPromote, }; +use crate::monadic::err::ErrMonadicTrans; use crate::monadic::ident::IdentMonadic; use crate::traits::{ContainsValue, LiftValue, MonadicBind}; @@ -52,6 +53,14 @@ where } } +// delegate_components! { +// +// BindOk { +// TryComputerComponent: +// TryPromote, TryPromote>>, +// } +// } + #[cgp_provider] impl TryComputer> for BindOk From 8a0beea9a69eaa1787de65d681edc2920c1df7e0 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 09:40:21 +0000 Subject: [PATCH 15/20] Trying to implement TryComputer through Computer --- crates/cgp-handler/src/providers/mod.rs | 2 +- .../cgp-handler/src/providers/try_promote.rs | 14 ++++----- crates/cgp-monad/src/monadic/err.rs | 8 +++-- crates/cgp-monad/src/monadic/ident.rs | 6 +++- crates/cgp-monad/src/monadic/ok.rs | 29 ++++++++++++++++--- crates/cgp-monad/src/traits/mod.rs | 2 ++ crates/cgp-monad/src/traits/monadic_trans.rs | 3 ++ 7 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 crates/cgp-monad/src/traits/monadic_trans.rs diff --git a/crates/cgp-handler/src/providers/mod.rs b/crates/cgp-handler/src/providers/mod.rs index 2d44bb45..39d270b6 100644 --- a/crates/cgp-handler/src/providers/mod.rs +++ b/crates/cgp-handler/src/providers/mod.rs @@ -12,4 +12,4 @@ pub use pipe::*; pub use promote::*; pub use promote_ref::*; pub use return_input::*; -pub use try_promote::*; \ No newline at end of file +pub use try_promote::*; diff --git a/crates/cgp-handler/src/providers/try_promote.rs b/crates/cgp-handler/src/providers/try_promote.rs index 35d77255..fe697e69 100644 --- a/crates/cgp-handler/src/providers/try_promote.rs +++ b/crates/cgp-handler/src/providers/try_promote.rs @@ -1,7 +1,7 @@ use cgp_core::prelude::*; use crate::{ - Computer, ComputerComponent, HandlerComponent, Promote, TryComputer, TryComputerComponent + Computer, ComputerComponent, HandlerComponent, Promote, TryComputer, TryComputerComponent, }; pub struct TryPromote(pub PhantomData); @@ -14,11 +14,11 @@ delegate_components! { } #[cgp_provider] -impl TryComputer +impl TryComputer for TryPromote where - Context: CanRaiseError, - Provider: Computer>, + Context: HasErrorType, + Provider: Computer>, { type Output = Output; @@ -27,14 +27,12 @@ where tag: PhantomData, input: Input, ) -> Result { - Provider::compute(context, tag, input).map_err(Context::raise_error) + Provider::compute(context, tag, input) } } - #[cgp_provider] -impl Computer - for TryPromote +impl Computer for TryPromote where Context: HasErrorType, Provider: TryComputer, diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 3c133a74..738fdd94 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -4,12 +4,16 @@ use cgp_handler::{ }; use crate::monadic::ident::IdentMonadic; -use crate::traits::{ContainsValue, LiftValue, MonadicBind}; +use crate::traits::{ContainsValue, LiftValue, MonadicBind, MonadicTrans}; pub struct ErrMonadic; pub struct ErrMonadicTrans(pub PhantomData); +impl MonadicTrans for ErrMonadic { + type M = ErrMonadicTrans; +} + impl MonadicBind for ErrMonadicTrans { type Provider = BindErr; } @@ -37,7 +41,7 @@ impl LiftValue> for ErrMonadic { impl ContainsValue for ErrMonadicTrans where - M: ContainsValue> + M: ContainsValue>, { type Value = T; } diff --git a/crates/cgp-monad/src/monadic/ident.rs b/crates/cgp-monad/src/monadic/ident.rs index fb254c62..0bedb5cf 100644 --- a/crates/cgp-monad/src/monadic/ident.rs +++ b/crates/cgp-monad/src/monadic/ident.rs @@ -1,7 +1,11 @@ -use crate::traits::{ContainsValue, LiftValue, MonadicBind}; +use crate::traits::{ContainsValue, LiftValue, MonadicBind, MonadicTrans}; pub struct IdentMonadic; +impl MonadicTrans for IdentMonadic { + type M = M; +} + impl MonadicBind for IdentMonadic { type Provider = Provider; } diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 74eb6179..93a023b2 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -1,9 +1,8 @@ use cgp_core::prelude::*; use cgp_handler::{ - Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, TryPromote, + Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; -use crate::monadic::err::ErrMonadicTrans; use crate::monadic::ident::IdentMonadic; use crate::traits::{ContainsValue, LiftValue, MonadicBind}; @@ -37,6 +36,28 @@ impl LiftValue> for OkMonadic { } } +impl ContainsValue for OkMonadicTrans +where + M: ContainsValue>, +{ + type Value = E; +} + +impl LiftValue for OkMonadicTrans +where + M: ContainsValue> + LiftValue, V>, +{ + type Output = M::Output; + + fn lift_value(value: E) -> Self::Output { + M::lift_value(Err(value)) + } + + fn lift_output(output: V) -> Self::Output { + M::lift_output(output) + } +} + #[cgp_provider] impl Computer> for BindOk where @@ -54,10 +75,10 @@ where } // delegate_components! { -// +// , Cont> // BindOk { // TryComputerComponent: -// TryPromote, TryPromote>>, +// TryPromote, TryPromote>>, // } // } diff --git a/crates/cgp-monad/src/traits/mod.rs b/crates/cgp-monad/src/traits/mod.rs index c8afefee..f612330a 100644 --- a/crates/cgp-monad/src/traits/mod.rs +++ b/crates/cgp-monad/src/traits/mod.rs @@ -1,7 +1,9 @@ mod bind; mod lift; +mod monadic_trans; mod value; pub use bind::*; pub use lift::*; +pub use monadic_trans::*; pub use value::*; diff --git a/crates/cgp-monad/src/traits/monadic_trans.rs b/crates/cgp-monad/src/traits/monadic_trans.rs new file mode 100644 index 00000000..8194d0de --- /dev/null +++ b/crates/cgp-monad/src/traits/monadic_trans.rs @@ -0,0 +1,3 @@ +pub trait MonadicTrans { + type M; +} From 66833b5214d6ef9a290faa144f2c1f0c1807ece1 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 10:34:15 +0000 Subject: [PATCH 16/20] Add tests for OkMonadic --- crates/cgp-tests/src/tests/monad/mod.rs | 2 + crates/cgp-tests/src/tests/monad/ok.rs | 53 +++++++++++++++++++ .../cgp-tests/src/tests/monad/ok_err_trans.rs | 28 ++++++++++ 3 files changed, 83 insertions(+) create mode 100644 crates/cgp-tests/src/tests/monad/ok.rs create mode 100644 crates/cgp-tests/src/tests/monad/ok_err_trans.rs diff --git a/crates/cgp-tests/src/tests/monad/mod.rs b/crates/cgp-tests/src/tests/monad/mod.rs index ce242b3f..61826bc1 100644 --- a/crates/cgp-tests/src/tests/monad/mod.rs +++ b/crates/cgp-tests/src/tests/monad/mod.rs @@ -1 +1,3 @@ pub mod err; +pub mod ok; +pub mod ok_err_trans; diff --git a/crates/cgp-tests/src/tests/monad/ok.rs b/crates/cgp-tests/src/tests/monad/ok.rs new file mode 100644 index 00000000..6891ed13 --- /dev/null +++ b/crates/cgp-tests/src/tests/monad/ok.rs @@ -0,0 +1,53 @@ +use cgp::extra::handler::PipeHandlers; +use cgp::extra::monad::monadic::ident::IdentMonadic; +use cgp::extra::monad::monadic::ok::{BindOk, OkMonadic}; +use cgp::extra::monad::providers::PipeMonadic; +use cgp::prelude::*; + +#[cgp_computer] +pub fn increment(value: u8) -> Result<&'static str, u8> { + match value.checked_add(1) { + Some(res) => Err(res), + None => Ok("overflow"), + } +} + +#[test] +fn test_increment_ok() { + let context = (); + let code = PhantomData::<()>; + + assert_eq!(Increment::compute(&context, code, 1), Err(2)); + assert_eq!(Increment::compute(&context, code, 255), Ok("overflow")); + + assert_eq!( + PipeHandlers::]>::compute( + &context, code, 1, + ), + Err(3), + ); + + assert_eq!( + PipeHandlers::]>::compute( + &context, code, 254, + ), + Ok("overflow"), + ); + + assert_eq!( + PipeMonadic::::compute(&context, code, 1), + Err(2), + ); + + assert_eq!( + PipeMonadic::::compute(&context, code, 255), + Ok("overflow"), + ); + + assert_eq!( + PipeMonadic::::compute( + &context, code, 253 + ), + Ok("overflow"), + ); +} diff --git a/crates/cgp-tests/src/tests/monad/ok_err_trans.rs b/crates/cgp-tests/src/tests/monad/ok_err_trans.rs new file mode 100644 index 00000000..5b094f3c --- /dev/null +++ b/crates/cgp-tests/src/tests/monad/ok_err_trans.rs @@ -0,0 +1,28 @@ +use cgp::prelude::*; +// use cgp::extra::monad::monadic::ok::{BindOk, OkMonadic, OkMonadicTrans}; + +#[cgp_computer] +pub fn return_ok_ok(_value: u8) -> Result, &'static str> { + Ok(Ok(())) +} + +#[cgp_computer] +pub fn return_ok_err(value: u8) -> Result, &'static str> { + Ok(Err(value)) +} + +#[cgp_computer] +pub fn return_err(_value: u8) -> Result, &'static str> { + Err("error") +} + +// #[test] +// pub fn test_monadic_trans() { +// let context = (); +// let code = PhantomData::<()>; + +// assert_eq!( +// PipeMonadic::::compute(&context, code, 1), +// Ok(Ok(1)), +// ); +// } From 75b0a1db2da4b36a492ee588f477cfd62497de05 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 10:52:45 +0000 Subject: [PATCH 17/20] Fix and test OkMonadicTrans --- crates/cgp-monad/src/monadic/err.rs | 7 ++- crates/cgp-monad/src/monadic/ok.rs | 7 ++- .../cgp-tests/src/tests/monad/ok_err_trans.rs | 50 +++++++++++++++---- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 738fdd94..1fc99735 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -14,8 +14,11 @@ impl MonadicTrans for ErrMonadic { type M = ErrMonadicTrans; } -impl MonadicBind for ErrMonadicTrans { - type Provider = BindErr; +impl MonadicBind for ErrMonadicTrans +where + M: MonadicBind>, +{ + type Provider = M::Provider; } impl MonadicBind for ErrMonadic { diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 93a023b2..83796488 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -12,8 +12,11 @@ pub struct OkMonadicTrans(pub PhantomData); pub struct BindOk(pub PhantomData<(M, Cont)>); -impl MonadicBind for OkMonadicTrans { - type Provider = BindOk; +impl MonadicBind for OkMonadicTrans +where + M: MonadicBind>, +{ + type Provider = M::Provider; } impl MonadicBind for OkMonadic { diff --git a/crates/cgp-tests/src/tests/monad/ok_err_trans.rs b/crates/cgp-tests/src/tests/monad/ok_err_trans.rs index 5b094f3c..5c3d809f 100644 --- a/crates/cgp-tests/src/tests/monad/ok_err_trans.rs +++ b/crates/cgp-tests/src/tests/monad/ok_err_trans.rs @@ -1,5 +1,8 @@ +use cgp::extra::monad::monadic::err::{BindErr, ErrMonadic}; +use cgp::extra::monad::monadic::ident::IdentMonadic; +use cgp::extra::monad::monadic::ok::{BindOk, OkMonadicTrans}; +use cgp::extra::monad::providers::PipeMonadic; use cgp::prelude::*; -// use cgp::extra::monad::monadic::ok::{BindOk, OkMonadic, OkMonadicTrans}; #[cgp_computer] pub fn return_ok_ok(_value: u8) -> Result, &'static str> { @@ -16,13 +19,40 @@ pub fn return_err(_value: u8) -> Result, &'static str> { Err("error") } -// #[test] -// pub fn test_monadic_trans() { -// let context = (); -// let code = PhantomData::<()>; +pub trait CheckImpl: + Computer< + (), + (), + Result, &'static str>, + Output = Result, &'static str>, +> +{ +} +impl CheckImpl for BindErr> {} + +#[test] +pub fn test_ok_err_monadic_trans() { + let context = (); + let code = PhantomData::<()>; + + assert_eq!( + PipeMonadic::, Product![ReturnOkErr, ReturnOkErr, ReturnOkErr]>::compute( + &context, code, 1 + ), + Ok(Err(1)), + ); -// assert_eq!( -// PipeMonadic::::compute(&context, code, 1), -// Ok(Ok(1)), -// ); -// } + assert_eq!( + PipeMonadic::, Product![ReturnOkErr, ReturnOkOk, ReturnOkErr]>::compute( + &context, code, 1 + ), + Ok(Ok(())), + ); + + assert_eq!( + PipeMonadic::, Product![ReturnErr, ReturnOkOk, ReturnOkErr]>::compute( + &context, code, 1 + ), + Err("error"), + ); +} From 1b5ba0012a06a815f0bc506ac7478c892dbc0d15 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 11:25:20 +0000 Subject: [PATCH 18/20] Implement MonadicTrans --- crates/cgp-monad/src/monadic/err.rs | 7 +++++++ crates/cgp-monad/src/monadic/ok.rs | 21 +++++++++++-------- .../cgp-monad/src/providers/pipe_monadic.rs | 10 ++++++--- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 1fc99735..4e5ae8ca 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -14,6 +14,13 @@ impl MonadicTrans for ErrMonadic { type M = ErrMonadicTrans; } +impl MonadicTrans for ErrMonadicTrans +where + M1: MonadicTrans, +{ + type M = ErrMonadicTrans; +} + impl MonadicBind for ErrMonadicTrans where M: MonadicBind>, diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 83796488..5e8e38cf 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -4,7 +4,7 @@ use cgp_handler::{ }; use crate::monadic::ident::IdentMonadic; -use crate::traits::{ContainsValue, LiftValue, MonadicBind}; +use crate::traits::{ContainsValue, LiftValue, MonadicBind, MonadicTrans}; pub struct OkMonadic; @@ -12,6 +12,17 @@ pub struct OkMonadicTrans(pub PhantomData); pub struct BindOk(pub PhantomData<(M, Cont)>); +impl MonadicTrans for OkMonadic { + type M = OkMonadicTrans; +} + +impl MonadicTrans for OkMonadicTrans +where + M1: MonadicTrans, +{ + type M = OkMonadicTrans; +} + impl MonadicBind for OkMonadicTrans where M: MonadicBind>, @@ -77,14 +88,6 @@ where } } -// delegate_components! { -// , Cont> -// BindOk { -// TryComputerComponent: -// TryPromote, TryPromote>>, -// } -// } - #[cgp_provider] impl TryComputer> for BindOk diff --git a/crates/cgp-monad/src/providers/pipe_monadic.rs b/crates/cgp-monad/src/providers/pipe_monadic.rs index 2baadfbc..87b5da61 100644 --- a/crates/cgp-monad/src/providers/pipe_monadic.rs +++ b/crates/cgp-monad/src/providers/pipe_monadic.rs @@ -1,14 +1,18 @@ use cgp_core::prelude::*; -use cgp_handler::ComposeHandlers; +use cgp_handler::{ComposeHandlers, HandlerComponent, ComputerComponent, TryComputerComponent}; use crate::traits::MonadicBind; pub struct PipeMonadic(pub PhantomData<(M, Providers)>); delegate_components! { - > + > PipeMonadic { - Component: Provider, + [ + ComputerComponent, + TryComputerComponent, + HandlerComponent, + ]: Provider, } } From 0cc0b1aea34af36d1ab0b546bea5df3c05d45a09 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 11:34:09 +0000 Subject: [PATCH 19/20] Generalized PipeMonadic composition for TryComputer is now working --- crates/cgp-monad/src/monadic/err.rs | 26 +-------------- crates/cgp-monad/src/monadic/ok.rs | 26 +-------------- .../cgp-monad/src/providers/pipe_monadic.rs | 32 +++++++++++++++++-- 3 files changed, 31 insertions(+), 53 deletions(-) diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index 4e5ae8ca..b98c2f19 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -1,7 +1,5 @@ use cgp_core::prelude::*; -use cgp_handler::{ - Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, -}; +use cgp_handler::{Computer, ComputerComponent, Handler, HandlerComponent}; use crate::monadic::ident::IdentMonadic; use crate::traits::{ContainsValue, LiftValue, MonadicBind, MonadicTrans}; @@ -87,28 +85,6 @@ where } } -#[cgp_provider] -impl TryComputer> - for BindErr -where - Context: HasErrorType, - Cont: TryComputer, - M: ContainsValue> + LiftValue, Cont::Output>, -{ - type Output = M::Output; - - fn try_compute( - context: &Context, - code: PhantomData, - input: Result, - ) -> Result { - match input { - Ok(value) => Ok(M::lift_output(Cont::try_compute(context, code, value)?)), - Err(err) => Ok(M::lift_value(Err(err))), - } - } -} - #[cgp_provider] impl Handler> for BindErr diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index 5e8e38cf..88df2986 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -1,7 +1,5 @@ use cgp_core::prelude::*; -use cgp_handler::{ - Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, -}; +use cgp_handler::{Computer, ComputerComponent, Handler, HandlerComponent}; use crate::monadic::ident::IdentMonadic; use crate::traits::{ContainsValue, LiftValue, MonadicBind, MonadicTrans}; @@ -88,28 +86,6 @@ where } } -#[cgp_provider] -impl TryComputer> - for BindOk -where - Context: HasErrorType, - Cont: TryComputer, - M: ContainsValue> + LiftValue, Cont::Output>, -{ - type Output = M::Output; - - fn try_compute( - context: &Context, - code: PhantomData, - input: Result, - ) -> Result { - match input { - Err(value) => Ok(M::lift_output(Cont::try_compute(context, code, value)?)), - Ok(err) => Ok(M::lift_value(Ok(err))), - } - } -} - #[cgp_provider] impl Handler> for BindOk diff --git a/crates/cgp-monad/src/providers/pipe_monadic.rs b/crates/cgp-monad/src/providers/pipe_monadic.rs index 87b5da61..5a458c28 100644 --- a/crates/cgp-monad/src/providers/pipe_monadic.rs +++ b/crates/cgp-monad/src/providers/pipe_monadic.rs @@ -1,7 +1,11 @@ +use cgp_core::field::MapFields; use cgp_core::prelude::*; -use cgp_handler::{ComposeHandlers, HandlerComponent, ComputerComponent, TryComputerComponent}; +use cgp_handler::{ + ComposeHandlers, ComputerComponent, HandlerComponent, TryComputerComponent, TryPromote, +}; -use crate::traits::MonadicBind; +use crate::monadic::err::ErrMonadic; +use crate::traits::{MonadicBind, MonadicTrans}; pub struct PipeMonadic(pub PhantomData<(M, Providers)>); @@ -10,12 +14,34 @@ delegate_components! { PipeMonadic { [ ComputerComponent, - TryComputerComponent, HandlerComponent, ]: Provider, } } +// Support monadic piping of TryComputer by first demoting them to Computer, +// together with a monad transformer application of ErrMonadic to the base monad, +// compose them, and then TryPromote them again back into TryComputer. + +delegate_components! { + < + Provider, + M1: MonadicTrans, + M2, + ProvidersA: MapFields, + ProvidersB: BindProviders, + > + PipeMonadic { + TryComputerComponent: TryPromote, + } +} + +pub struct TryPromoteProviders; + +impl MapType for TryPromoteProviders { + type Map = TryPromote; +} + trait BindProviders { type Provider; } From 60235802c2d599b6e9649c07f7583964155a17c6 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 17 Jul 2025 11:42:04 +0000 Subject: [PATCH 20/20] Add more tests for use of monadic transformers --- crates/cgp-error/src/contexts/error_only.rs | 16 +++++ crates/cgp-error/src/contexts/mod.rs | 3 + crates/cgp-error/src/lib.rs | 8 +-- .../cgp-tests/src/tests/monad/ok_err_trans.rs | 65 ++++++++++++++----- 4 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 crates/cgp-error/src/contexts/error_only.rs create mode 100644 crates/cgp-error/src/contexts/mod.rs diff --git a/crates/cgp-error/src/contexts/error_only.rs b/crates/cgp-error/src/contexts/error_only.rs new file mode 100644 index 00000000..59a5477b --- /dev/null +++ b/crates/cgp-error/src/contexts/error_only.rs @@ -0,0 +1,16 @@ +use core::fmt::Debug; +use core::marker::PhantomData; + +use crate::HasErrorType; + +pub struct ErrorOnly(pub PhantomData); + +impl Default for ErrorOnly { + fn default() -> Self { + Self(PhantomData) + } +} + +impl HasErrorType for ErrorOnly { + type Error = E; +} diff --git a/crates/cgp-error/src/contexts/mod.rs b/crates/cgp-error/src/contexts/mod.rs new file mode 100644 index 00000000..fe6a70c3 --- /dev/null +++ b/crates/cgp-error/src/contexts/mod.rs @@ -0,0 +1,3 @@ +mod error_only; + +pub use error_only::*; diff --git a/crates/cgp-error/src/lib.rs b/crates/cgp-error/src/lib.rs index 2744fb4c..56a70f70 100644 --- a/crates/cgp-error/src/lib.rs +++ b/crates/cgp-error/src/lib.rs @@ -1,9 +1,7 @@ #![no_std] +mod contexts; mod traits; -pub use traits::{ - CanRaiseAsyncError, CanRaiseError, CanWrapAsyncError, CanWrapError, ErrorOf, ErrorRaiser, - ErrorRaiserComponent, ErrorTypeProvider, ErrorTypeProviderComponent, ErrorWrapper, - ErrorWrapperComponent, HasAsyncErrorType, HasErrorType, -}; +pub use contexts::*; +pub use traits::*; diff --git a/crates/cgp-tests/src/tests/monad/ok_err_trans.rs b/crates/cgp-tests/src/tests/monad/ok_err_trans.rs index 5c3d809f..6766b395 100644 --- a/crates/cgp-tests/src/tests/monad/ok_err_trans.rs +++ b/crates/cgp-tests/src/tests/monad/ok_err_trans.rs @@ -1,8 +1,9 @@ -use cgp::extra::monad::monadic::err::{BindErr, ErrMonadic}; -use cgp::extra::monad::monadic::ident::IdentMonadic; -use cgp::extra::monad::monadic::ok::{BindOk, OkMonadicTrans}; +use cgp::core::error::ErrorOnly; +use cgp::extra::monad::monadic::err::ErrMonadic; +use cgp::extra::monad::monadic::ok::{OkMonadic, OkMonadicTrans}; use cgp::extra::monad::providers::PipeMonadic; use cgp::prelude::*; +use futures::executor::block_on; #[cgp_computer] pub fn return_ok_ok(_value: u8) -> Result, &'static str> { @@ -19,20 +20,9 @@ pub fn return_err(_value: u8) -> Result, &'static str> { Err("error") } -pub trait CheckImpl: - Computer< - (), - (), - Result, &'static str>, - Output = Result, &'static str>, -> -{ -} -impl CheckImpl for BindErr> {} - #[test] pub fn test_ok_err_monadic_trans() { - let context = (); + let context = ErrorOnly::<&'static str>::default(); let code = PhantomData::<()>; assert_eq!( @@ -55,4 +45,49 @@ pub fn test_ok_err_monadic_trans() { ), Err("error"), ); + + assert_eq!( + PipeMonadic::::try_compute( + &context, code, 1 + ), + Ok(Err(1)), + ); + + assert_eq!( + PipeMonadic::::try_compute( + &context, code, 1 + ), + Ok(Ok(())), + ); + + assert_eq!( + PipeMonadic::::try_compute( + &context, code, 1 + ), + Err("error"), + ); + + assert_eq!( + block_on(PipeMonadic::< + OkMonadic, + Product![ReturnOkErr, ReturnOkErr, ReturnOkErr], + >::handle(&context, code, 1)), + Ok(Err(1)), + ); + + assert_eq!( + block_on(PipeMonadic::< + OkMonadic, + Product![ReturnOkErr, ReturnOkOk, ReturnOkErr], + >::handle(&context, code, 1)), + Ok(Ok(())), + ); + + assert_eq!( + block_on(PipeMonadic::< + OkMonadic, + Product![ReturnErr, ReturnOkOk, ReturnOkErr], + >::handle(&context, code, 1)), + Err("error"), + ); }