diff --git a/src/func/instances/composition.rs b/src/func/instances/composition.rs index 37b7cc5..b378a4a 100644 --- a/src/func/instances/composition.rs +++ b/src/func/instances/composition.rs @@ -214,4 +214,9 @@ mod composition_tests { fn monad_follows_laws() { test_suite::monad_follows_laws::().unwrap(); } + + #[test] + fn shared_follows_laws() { + test_suite::shared_follows_laws::().unwrap(); + } } diff --git a/src/func/instances/effect.rs b/src/func/instances/effect.rs index 9fef2ea..27eac1e 100644 --- a/src/func/instances/effect.rs +++ b/src/func/instances/effect.rs @@ -166,12 +166,12 @@ mod effect_tests { use super::{test_suite, tests, Effect, EffectInstance, WithEffect}; - #[derive(Debug, PartialEq)] + #[derive(Clone, Debug, PartialEq)] enum TestEffect { Pure, Sample, - Parallel(Box, Box), - Sequential(Box, Box), + Parallel(Arc, Arc), + Sequential(Arc, Arc), } impl TestEffect { @@ -179,25 +179,27 @@ mod effect_tests { matches!(self, Self::Pure) } - fn simplify(self) -> Self { + fn simplify(&self) -> Arc { match self { - Self::Pure => Self::Pure, - Self::Sample => Self::Sample, - Self::Parallel(a, b) if a.is_pure() => *b, - Self::Parallel(a, b) if b.is_pure() => *a, - Self::Sequential(a, b) if a.is_pure() => *b, - Self::Sequential(a, b) if b.is_pure() => *a, - Self::Parallel(a, b) => match *a { + Self::Pure => Self::Pure.into(), + Self::Sample => Self::Sample.into(), + Self::Parallel(a, b) if a.is_pure() => b.clone(), + Self::Parallel(a, b) if b.is_pure() => a.clone(), + Self::Sequential(a, b) if a.is_pure() => b.clone(), + Self::Sequential(a, b) if b.is_pure() => a.clone(), + Self::Parallel(a, b) => match a.as_ref() { Self::Parallel(aa, ab) => { - Self::Parallel(aa, Self::Parallel(ab, b).into()).simplify() + Self::Parallel(aa.clone(), Self::Parallel(ab.clone(), b.clone()).into()) + .simplify() } - a => Self::Parallel(a.simplify().into(), b.simplify().into()), + a => Self::Parallel(a.simplify(), b.simplify()).into(), }, - Self::Sequential(a, b) => match *a { + Self::Sequential(a, b) => match a.as_ref() { TestEffect::Sequential(aa, ab) => { - Self::Sequential(aa, Self::Sequential(ab, b).into()).simplify() + Self::Sequential(aa.clone(), Self::Sequential(ab.clone(), b.clone()).into()) + .simplify() } - a => Self::Sequential(a.simplify().into(), b.simplify().into()), + a => Self::Sequential(a.simplify().clone(), b.simplify().clone()).into(), }, } } @@ -248,4 +250,9 @@ mod effect_tests { fn monad_follows_laws() { test_suite::monad_follows_laws::().unwrap(); } + + #[test] + fn shared_follows_laws() { + test_suite::shared_follows_laws::().unwrap(); + } } diff --git a/src/func/instances/future.rs b/src/func/instances/future.rs index 8c2208b..7358f05 100644 --- a/src/func/instances/future.rs +++ b/src/func/instances/future.rs @@ -184,4 +184,9 @@ mod future_tests { Selected::B(_, b) => assert_eq!(b, 2), } } + + #[test] + fn shared_follows_laws() { + test_suite::shared_follows_laws::().unwrap(); + } } diff --git a/src/func/instances/option.rs b/src/func/instances/option.rs index b6e0578..fc2fc70 100644 --- a/src/func/instances/option.rs +++ b/src/func/instances/option.rs @@ -185,4 +185,9 @@ mod option_tests { fn monad_follows_laws() { test_suite::monad_follows_laws::().unwrap(); } + + #[test] + fn shared_follows_laws() { + test_suite::shared_follows_laws::().unwrap(); + } } diff --git a/src/func/instances/result.rs b/src/func/instances/result.rs index 7f25683..f2515bb 100644 --- a/src/func/instances/result.rs +++ b/src/func/instances/result.rs @@ -280,4 +280,9 @@ mod result_tests { fn monad_follows_laws() { test_suite::monad_follows_laws::().unwrap(); } + + #[test] + fn shared_follows_laws() { + test_suite::shared_follows_laws::().unwrap(); + } } diff --git a/src/func/instances/solo.rs b/src/func/instances/solo.rs index ac5f5a1..1eda3f3 100644 --- a/src/func/instances/solo.rs +++ b/src/func/instances/solo.rs @@ -147,4 +147,9 @@ mod solo_tests { fn monad_follows_laws() { test_suite::monad_follows_laws::().unwrap(); } + + #[test] + fn shared_follows_laws() { + test_suite::shared_follows_laws::().unwrap(); + } } diff --git a/src/func/instances/tryfuture.rs b/src/func/instances/tryfuture.rs index 89b1783..09a0fac 100644 --- a/src/func/instances/tryfuture.rs +++ b/src/func/instances/tryfuture.rs @@ -256,4 +256,9 @@ mod tryfuture_tests { Selected::B(_, b) => assert_eq!(b, 2), } } + + #[test] + fn shared_follows_laws() { + test_suite::shared_follows_laws::().unwrap(); + } } diff --git a/src/func/test_suite.rs b/src/func/test_suite.rs index fba8de6..49dfa5c 100644 --- a/src/func/test_suite.rs +++ b/src/func/test_suite.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use shared::SharedFunctor; + use super::tests::*; use super::*; @@ -119,3 +121,11 @@ pub fn monad_follows_laws<'a, T: Monad<'a> + FunctorTestSuite<'a>>() -> R { }); res } + +pub fn shared_follows_laws<'a, T: SharedFunctor<'a> + FunctorTestSuite<'a>>() -> R { + let mut res = R::default(); + T::sample(|pa| { + res += shared_is_same_as_original::(move || pa(2)); + }); + res +} diff --git a/src/func/tests.rs b/src/func/tests.rs index 07ef32a..d110b3f 100644 --- a/src/func/tests.rs +++ b/src/func/tests.rs @@ -5,6 +5,7 @@ use std::{ use applicative_select::Selected; use controlflow::IterativeWrapped; +use shared::SharedFunctor; use super::*; @@ -448,3 +449,17 @@ pub fn select_of_equal_is_same< fa0(), ) } + +pub fn shared_is_same_as_original< + 'a, + T: SharedFunctor<'a> + Eqr<'a>, + A: 'a + Send + Sync + Clone + Debug + PartialEq, +>( + fa0: impl 'a + Fn() -> T::F, +) -> R { + T::eqr( + "shared same as original", + T::unshare(T::share(fa0())), + fa0(), + ) +}