fail_follows_laws
Some checks failed
buildbot/cargo fmt (1.72) Build done.
buildbot/cargo doc (1.72) Build done.
buildbot/cargo clippy (1.65) Build done.
buildbot/cargo clippy (1.72) Build done.
buildbot/cargo test (1.65) Build done.

This commit is contained in:
AF 2023-10-15 18:05:36 +00:00
parent 787efb3662
commit 7f37bcbd49
3 changed files with 51 additions and 9 deletions

View File

@ -12,6 +12,8 @@
//! [`result`]: super::result //! [`result`]: super::result
//! [`solo`]: super::solo //! [`solo`]: super::solo
use std::convert::Infallible;
use crate::func::class_prelude::*; use crate::func::class_prelude::*;
#[derive(SharedFunctorAny)] #[derive(SharedFunctorAny)]
@ -126,14 +128,18 @@ impl<'a> LocalFunctor<'a> for OptionInstance {
} }
} }
impl<'a> Fail<'a, ()> for OptionInstance { impl<'a> Fail<'a, Option<Infallible>> for OptionInstance {
fn fail<A: 'a + Send>(_e: ()) -> Self::F<A> { fn fail<A: 'a + Send>(e: Option<Infallible>) -> Self::F<A> {
None match e {
Some(some) => match some {},
None => None,
}
} }
} }
#[cfg(test)] #[cfg(test)]
mod option_tests { mod option_tests {
use std::convert::Infallible;
use std::sync::Arc; use std::sync::Arc;
use super::{test_suite, tests, Functor}; use super::{test_suite, tests, Functor};
@ -159,6 +165,12 @@ mod option_tests {
} }
} }
impl<'a> test_suite::FailTestSuite<'a, Option<Infallible>> for T {
fn sample_fail<F: FnMut(Arc<dyn 'a + Send + Sync + Fn() -> Option<Infallible>>)>(mut f: F) {
f(Arc::new(|| None))
}
}
#[test] #[test]
fn fmap_f_none_is_none() { fn fmap_f_none_is_none() {
assert_eq!(T::fmap(None, |_: ()| ()), None); assert_eq!(T::fmap(None, |_: ()| ()), None);
@ -190,4 +202,9 @@ mod option_tests {
fn shared_follows_laws() { fn shared_follows_laws() {
test_suite::shared_follows_laws::<T>().unwrap(); test_suite::shared_follows_laws::<T>().unwrap();
} }
#[test]
fn fail_follows_laws() {
test_suite::fail_functor_follows_laws::<T, _>().unwrap();
}
} }

View File

@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use shared::SharedFunctor; use super::fail::*;
use super::shared::*;
use super::tests::*; use super::tests::*;
use super::*; use super::*;
@ -13,6 +13,10 @@ pub trait FunctorTestSuite<'a>: WeakFunctor<'a> + Eqr<'a> {
fn sample<A: 'a + Send, F: FnMut(Arc<dyn WrapFunction<'a, A, Self::F<A>>>)>(f: F); fn sample<A: 'a + Send, F: FnMut(Arc<dyn WrapFunction<'a, A, Self::F<A>>>)>(f: F);
} }
pub trait FailTestSuite<'a, E: 'a + Send>: FunctorTestSuite<'a> + Fail<'a, E> {
fn sample_fail<F: FnMut(Arc<dyn 'a + Send + Sync + Fn() -> E>)>(f: F);
}
pub fn functor_follows_laws<'a, T: Functor<'a> + FunctorTestSuite<'a>>() -> R { pub fn functor_follows_laws<'a, T: Functor<'a> + FunctorTestSuite<'a>>() -> R {
let mut res = R::default(); let mut res = R::default();
T::sample(|pa| { T::sample(|pa| {
@ -132,3 +136,11 @@ pub fn shared_follows_laws<'a, T: SharedFunctor<'a> + FunctorTestSuite<'a>>() ->
}); });
res res
} }
pub fn fail_functor_follows_laws<'a, T: Functor<'a> + FailTestSuite<'a, E>, E: 'a + Send>() -> R {
let mut res = R::default();
T::sample_fail(|pe| {
res += fmap_keeps_fail::<T, _, _, _>(move || pe(), |x: i32| x + 2);
});
res
}

View File

@ -3,10 +3,10 @@ use std::{
ops::{Add, AddAssign}, ops::{Add, AddAssign},
}; };
use applicative_select::Selected; use super::applicative_select::*;
use controlflow::IterativeWrapped; use super::controlflow::*;
use shared::SharedFunctor; use super::fail::*;
use super::shared::*;
use super::*; use super::*;
pub struct TestResults { pub struct TestResults {
@ -478,3 +478,16 @@ pub fn shared_is_same_after_clone<
T::unshare(sa), T::unshare(sa),
) )
} }
pub fn fmap_keeps_fail<
'a,
T: Functor<'a> + Fail<'a, E> + Eqr<'a>,
A: 'a + Send,
B: 'a + Send + Debug + PartialEq,
E: 'a + Send,
>(
e0: impl 'a + Send + Fn() -> E,
f: impl 'a + Send + Fn(A) -> B,
) -> R {
T::eqr("fmap fail", T::fmap(T::fail(e0()), f), T::fail(e0()))
}