#[fp_macros::document_module]
mod inner {
pub struct Val;
pub struct Ref;
pub trait ClosureMode {
type Target<'a, A: 'a, B: 'a>: ?Sized + 'a;
type SendTarget<'a, A: 'a, B: 'a>: ?Sized + 'a;
}
impl ClosureMode for Val {
type SendTarget<'a, A: 'a, B: 'a> = dyn 'a + Fn(A) -> B + Send + Sync;
type Target<'a, A: 'a, B: 'a> = dyn 'a + Fn(A) -> B;
}
impl ClosureMode for Ref {
type SendTarget<'a, A: 'a, B: 'a> = dyn 'a + Fn(&A) -> B + Send + Sync;
type Target<'a, A: 'a, B: 'a> = dyn 'a + Fn(&A) -> B;
}
}
pub use inner::*;
pub mod alt;
pub mod apply_first;
pub mod apply_second;
pub mod bifoldable;
pub mod bifunctor;
pub mod bitraversable;
pub mod compactable;
pub mod contravariant;
pub mod filterable;
pub mod filterable_with_index;
pub mod foldable;
pub mod foldable_with_index;
pub mod functor;
pub mod functor_with_index;
pub mod lift;
pub mod semimonad;
pub mod traversable;
pub mod traversable_with_index;
pub mod witherable;
#[cfg(test)]
mod tests {
use {
super::{
functor::explicit::map,
lift::explicit::lift2,
semimonad::explicit::bind,
},
crate::{
brands::*,
types::*,
},
};
#[test]
fn test_val_option_map() {
let result = map::<OptionBrand, _, _, _, _>(|x: i32| x * 2, Some(5));
assert_eq!(result, Some(10));
}
#[test]
fn test_val_vec_map() {
let result = map::<VecBrand, _, _, _, _>(|x: i32| x + 1, vec![1, 2, 3]);
assert_eq!(result, vec![2, 3, 4]);
}
#[test]
fn test_ref_lazy_map() {
let lazy = RcLazy::pure(10);
let result = map::<LazyBrand<RcLazyConfig>, _, _, _, _>(|x: &i32| *x * 2, &lazy);
assert_eq!(*result.evaluate(), 20);
}
#[test]
fn test_val_none_map() {
let result = map::<OptionBrand, i32, i32, _, _>(|x| x * 2, None);
assert_eq!(result, None);
}
#[test]
fn test_val_option_bind() {
let result = bind::<OptionBrand, _, _, _, _>(Some(5), |x: i32| Some(x * 2));
assert_eq!(result, Some(10));
}
#[test]
fn test_val_option_lift2() {
let result = lift2::<OptionBrand, _, _, _, _, _, _>(|a, b| a + b, Some(1), Some(2));
assert_eq!(result, Some(3));
}
#[test]
fn test_val_option_filter_map() {
use super::filterable::explicit::filter_map;
let result = filter_map::<OptionBrand, _, _, _, _>(
|x: i32| if x > 3 { Some(x * 2) } else { None },
Some(5),
);
assert_eq!(result, Some(10));
}
#[test]
fn test_val_option_filter_map_none() {
use super::filterable::explicit::filter_map;
let result = filter_map::<OptionBrand, _, _, _, _>(
|x: i32| if x > 10 { Some(x) } else { None },
Some(5),
);
assert_eq!(result, None);
}
#[test]
fn test_ref_option_filter_map() {
use super::filterable::explicit::filter_map;
let result = filter_map::<OptionBrand, _, _, _, _>(
|x: &i32| if *x > 3 { Some(*x * 2) } else { None },
&Some(5),
);
assert_eq!(result, Some(10));
}
#[test]
fn test_val_vec_filter_map() {
use super::filterable::explicit::filter_map;
let result = filter_map::<VecBrand, _, _, _, _>(
|x: i32| if x > 2 { Some(x * 10) } else { None },
vec![1, 2, 3, 4],
);
assert_eq!(result, vec![30, 40]);
}
#[test]
fn test_ref_vec_filter_map() {
use super::filterable::explicit::filter_map;
let v = vec![1, 2, 3, 4];
let result = filter_map::<VecBrand, _, _, _, _>(
|x: &i32| if *x > 2 { Some(*x * 10) } else { None },
&v,
);
assert_eq!(result, vec![30, 40]);
}
#[test]
fn test_val_option_traverse() {
use super::traversable::explicit::traverse;
let result = traverse::<RcFnBrand, OptionBrand, _, _, OptionBrand, _, _>(
|x: i32| Some(x * 2),
Some(5),
);
assert_eq!(result, Some(Some(10)));
}
#[test]
fn test_val_option_traverse_none() {
use super::traversable::explicit::traverse;
let result = traverse::<RcFnBrand, OptionBrand, _, _, OptionBrand, _, _>(
|_: i32| None::<i32>,
Some(5),
);
assert_eq!(result, None);
}
#[test]
fn test_ref_option_traverse() {
use super::traversable::explicit::traverse;
let result = traverse::<RcFnBrand, OptionBrand, _, _, OptionBrand, _, _>(
|x: &i32| Some(*x * 2),
&Some(5),
);
assert_eq!(result, Some(Some(10)));
}
#[test]
fn test_val_vec_traverse() {
use super::traversable::explicit::traverse;
let result: Option<Vec<i32>> = traverse::<RcFnBrand, VecBrand, _, _, OptionBrand, _, _>(
|x: i32| Some(x * 2),
vec![1, 2, 3],
);
assert_eq!(result, Some(vec![2, 4, 6]));
}
#[test]
fn test_ref_vec_traverse() {
use super::traversable::explicit::traverse;
let v = vec![1, 2, 3];
let result: Option<Vec<i32>> =
traverse::<RcFnBrand, VecBrand, _, _, OptionBrand, _, _>(|x: &i32| Some(*x * 2), &v);
assert_eq!(result, Some(vec![2, 4, 6]));
}
#[test]
fn test_val_option_filter() {
use super::filterable::explicit::filter;
let result = filter::<OptionBrand, _, _, _>(|x: i32| x > 3, Some(5));
assert_eq!(result, Some(5));
}
#[test]
fn test_ref_option_filter() {
use super::filterable::explicit::filter;
let result = filter::<OptionBrand, _, _, _>(|x: &i32| *x > 3, &Some(5));
assert_eq!(result, Some(5));
}
#[test]
fn test_val_vec_filter() {
use super::filterable::explicit::filter;
let result = filter::<VecBrand, _, _, _>(|x: i32| x > 3, vec![1, 2, 3, 4, 5]);
assert_eq!(result, vec![4, 5]);
}
#[test]
fn test_ref_vec_filter() {
use super::filterable::explicit::filter;
let v = vec![1, 2, 3, 4, 5];
let result = filter::<VecBrand, _, _, _>(|x: &i32| *x > 3, &v);
assert_eq!(result, vec![4, 5]);
}
#[test]
fn test_val_option_partition() {
use super::filterable::explicit::partition;
let (no, yes) = partition::<OptionBrand, _, _, _>(|x: i32| x > 3, Some(5));
assert_eq!(yes, Some(5));
assert_eq!(no, None);
}
#[test]
fn test_ref_option_partition() {
use super::filterable::explicit::partition;
let (no, yes) = partition::<OptionBrand, _, _, _>(|x: &i32| *x > 3, &Some(5));
assert_eq!(yes, Some(5));
assert_eq!(no, None);
}
#[test]
fn test_val_option_partition_map() {
use super::filterable::explicit::partition_map;
let (errs, oks) =
partition_map::<OptionBrand, _, _, _, _, _>(|x: i32| Ok::<i32, i32>(x * 2), Some(5));
assert_eq!(errs, None);
assert_eq!(oks, Some(10));
}
#[test]
fn test_ref_option_partition_map() {
use super::filterable::explicit::partition_map;
let (errs, oks) =
partition_map::<OptionBrand, _, _, _, _, _>(|x: &i32| Ok::<i32, i32>(*x * 2), &Some(5));
assert_eq!(errs, None);
assert_eq!(oks, Some(10));
}
#[test]
fn test_val_vec_map_with_index() {
use super::functor_with_index::explicit::map_with_index;
let result =
map_with_index::<VecBrand, _, _, _, _>(|i, x: i32| x + i as i32, vec![10, 20, 30]);
assert_eq!(result, vec![10, 21, 32]);
}
#[test]
fn test_ref_vec_map_with_index() {
use super::functor_with_index::explicit::map_with_index;
let v = vec![10, 20, 30];
let result = map_with_index::<VecBrand, _, _, _, _>(|i, x: &i32| *x + i as i32, &v);
assert_eq!(result, vec![10, 21, 32]);
}
#[test]
fn test_val_vec_filter_with_index() {
use super::filterable_with_index::explicit::filter_with_index;
let result =
filter_with_index::<VecBrand, _, _, _>(|i, _x: i32| i < 2, vec![10, 20, 30, 40]);
assert_eq!(result, vec![10, 20]);
}
#[test]
fn test_ref_vec_filter_with_index() {
use super::filterable_with_index::explicit::filter_with_index;
let v = vec![10, 20, 30, 40];
let result = filter_with_index::<VecBrand, _, _, _>(|i, _x: &i32| i < 2, &v);
assert_eq!(result, vec![10, 20]);
}
#[test]
fn test_val_vec_filter_map_with_index() {
use super::filterable_with_index::explicit::filter_map_with_index;
let result = filter_map_with_index::<VecBrand, _, _, _, _>(
|i, x: i32| if i % 2 == 0 { Some(x * 2) } else { None },
vec![10, 20, 30, 40],
);
assert_eq!(result, vec![20, 60]);
}
#[test]
fn test_ref_vec_filter_map_with_index() {
use super::filterable_with_index::explicit::filter_map_with_index;
let v = vec![10, 20, 30, 40];
let result = filter_map_with_index::<VecBrand, _, _, _, _>(
|i, x: &i32| if i % 2 == 0 { Some(*x * 2) } else { None },
&v,
);
assert_eq!(result, vec![20, 60]);
}
#[test]
fn test_val_vec_partition_with_index() {
use super::filterable_with_index::explicit::partition_with_index;
let (not_satisfied, satisfied) =
partition_with_index::<VecBrand, _, _, _>(|i, _x: i32| i < 2, vec![10, 20, 30, 40]);
assert_eq!(satisfied, vec![10, 20]);
assert_eq!(not_satisfied, vec![30, 40]);
}
#[test]
fn test_ref_vec_partition_with_index() {
use super::filterable_with_index::explicit::partition_with_index;
let v = vec![10, 20, 30, 40];
let (not_satisfied, satisfied) =
partition_with_index::<VecBrand, _, _, _>(|i, _x: &i32| i < 2, &v);
assert_eq!(satisfied, vec![10, 20]);
assert_eq!(not_satisfied, vec![30, 40]);
}
#[test]
fn test_val_vec_partition_map_with_index() {
use super::filterable_with_index::explicit::partition_map_with_index;
let (errs, oks) = partition_map_with_index::<VecBrand, _, _, _, _, _>(
|i, x: i32| if i < 2 { Ok(x) } else { Err(x) },
vec![10, 20, 30, 40],
);
assert_eq!(oks, vec![10, 20]);
assert_eq!(errs, vec![30, 40]);
}
#[test]
fn test_ref_vec_partition_map_with_index() {
use super::filterable_with_index::explicit::partition_map_with_index;
let v = vec![10, 20, 30, 40];
let (errs, oks) = partition_map_with_index::<VecBrand, _, _, _, _, _>(
|i, x: &i32| if i < 2 { Ok(*x) } else { Err(*x) },
&v,
);
assert_eq!(oks, vec![10, 20]);
assert_eq!(errs, vec![30, 40]);
}
#[test]
fn test_val_vec_fold_map_with_index() {
use super::foldable_with_index::explicit::fold_map_with_index;
let result = fold_map_with_index::<RcFnBrand, VecBrand, _, _, _, _>(
|i, x: i32| format!("{i}:{x}"),
vec![10, 20, 30],
);
assert_eq!(result, "0:101:202:30");
}
#[test]
fn test_ref_vec_fold_map_with_index() {
use super::foldable_with_index::explicit::fold_map_with_index;
let v = vec![10, 20, 30];
let result = fold_map_with_index::<RcFnBrand, VecBrand, _, _, _, _>(
|i, x: &i32| format!("{i}:{x}"),
&v,
);
assert_eq!(result, "0:101:202:30");
}
#[test]
fn test_val_vec_fold_right_with_index() {
use super::foldable_with_index::explicit::fold_right_with_index;
let result = fold_right_with_index::<RcFnBrand, VecBrand, _, _, _, _>(
|i, x: i32, acc: String| format!("{acc}{i}:{x},"),
String::new(),
vec![10, 20, 30],
);
assert_eq!(result, "2:30,1:20,0:10,");
}
#[test]
fn test_ref_vec_fold_right_with_index() {
use super::foldable_with_index::explicit::fold_right_with_index;
let v = vec![10, 20, 30];
let result = fold_right_with_index::<RcFnBrand, VecBrand, _, _, _, _>(
|i, x: &i32, acc: String| format!("{acc}{i}:{x},"),
String::new(),
&v,
);
assert_eq!(result, "2:30,1:20,0:10,");
}
#[test]
fn test_val_vec_fold_left_with_index() {
use super::foldable_with_index::explicit::fold_left_with_index;
let result = fold_left_with_index::<RcFnBrand, VecBrand, _, _, _, _>(
|i, acc: String, x: i32| format!("{acc}{i}:{x},"),
String::new(),
vec![10, 20, 30],
);
assert_eq!(result, "0:10,1:20,2:30,");
}
#[test]
fn test_ref_vec_fold_left_with_index() {
use super::foldable_with_index::explicit::fold_left_with_index;
let v = vec![10, 20, 30];
let result = fold_left_with_index::<RcFnBrand, VecBrand, _, _, _, _>(
|i, acc: String, x: &i32| format!("{acc}{i}:{x},"),
String::new(),
&v,
);
assert_eq!(result, "0:10,1:20,2:30,");
}
#[test]
fn test_val_vec_traverse_with_index() {
use super::traversable_with_index::explicit::traverse_with_index;
let result = traverse_with_index::<RcFnBrand, VecBrand, _, _, OptionBrand, _, _>(
|_i, x: i32| Some(x * 2),
vec![1, 2, 3],
);
assert_eq!(result, Some(vec![2, 4, 6]));
}
#[test]
fn test_ref_vec_traverse_with_index() {
use super::traversable_with_index::explicit::traverse_with_index;
let v = vec![1, 2, 3];
let result = traverse_with_index::<RcFnBrand, VecBrand, _, _, OptionBrand, _, _>(
|_i, x: &i32| Some(*x * 2),
&v,
);
assert_eq!(result, Some(vec![2, 4, 6]));
}
#[test]
fn test_val_option_wilt() {
use super::witherable::explicit::wilt;
let result = wilt::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _, _>(
|a: i32| Some(if a > 2 { Ok(a) } else { Err(a) }),
Some(5),
);
assert_eq!(result, Some((None, Some(5))));
}
#[test]
fn test_ref_vec_wilt() {
use super::witherable::explicit::wilt;
let v = vec![1, 2, 3, 4, 5];
let result: Option<(Vec<i32>, Vec<i32>)> =
wilt::<RcFnBrand, VecBrand, OptionBrand, _, _, _, _, _>(
|x: &i32| Some(if *x > 3 { Ok(*x) } else { Err(*x) }),
&v,
);
assert_eq!(result, Some((vec![1, 2, 3], vec![4, 5])));
}
#[test]
fn test_val_option_wither() {
use super::witherable::explicit::wither;
let result = wither::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _>(
|a: i32| Some(if a > 2 { Some(a * 2) } else { None }),
Some(5),
);
assert_eq!(result, Some(Some(10)));
}
#[test]
fn test_ref_vec_wither() {
use super::witherable::explicit::wither;
let v = vec![1, 2, 3, 4, 5];
let result: Option<Vec<i32>> = wither::<RcFnBrand, VecBrand, OptionBrand, _, _, _, _>(
|x: &i32| if *x > 3 { Some(Some(*x)) } else { Some(None) },
&v,
);
assert_eq!(result, Some(vec![4, 5]));
}
#[test]
fn test_val_result_bimap() {
use super::bifunctor::explicit::bimap;
let x = Result::<i32, i32>::Ok(5);
let y = bimap::<ResultBrand, _, _, _, _, _, _>((|e| e + 1, |s| s * 2), x);
assert_eq!(y, Ok(10));
}
#[test]
fn test_val_result_bimap_err() {
use super::bifunctor::explicit::bimap;
let x = Result::<i32, i32>::Err(3);
let y = bimap::<ResultBrand, _, _, _, _, _, _>((|e| e + 1, |s| s * 2), x);
assert_eq!(y, Err(4));
}
#[test]
fn test_ref_result_bimap() {
use super::bifunctor::explicit::bimap;
let x = Result::<i32, i32>::Ok(5);
let y = bimap::<ResultBrand, _, _, _, _, _, _>((|e: &i32| *e + 1, |s: &i32| *s * 2), &x);
assert_eq!(y, Ok(10));
}
#[test]
fn test_val_result_bi_fold_right() {
use super::bifoldable::explicit::bi_fold_right;
let x: Result<i32, i32> = Err(3);
let y = bi_fold_right::<RcFnBrand, ResultBrand, _, _, _, _, _>(
(|e, acc| acc - e, |s, acc| acc + s),
10,
x,
);
assert_eq!(y, 7);
}
#[test]
fn test_ref_result_bi_fold_right() {
use super::bifoldable::explicit::bi_fold_right;
let x: Result<i32, i32> = Err(3);
let y = bi_fold_right::<RcFnBrand, ResultBrand, _, _, _, _, _>(
(|e: &i32, acc| acc - *e, |s: &i32, acc| acc + *s),
10,
&x,
);
assert_eq!(y, 7);
}
#[test]
fn test_val_result_bi_fold_left() {
use super::bifoldable::explicit::bi_fold_left;
let x: Result<i32, i32> = Ok(5);
let y = bi_fold_left::<RcFnBrand, ResultBrand, _, _, _, _, _>(
(|acc, e| acc - e, |acc, s| acc + s),
10,
x,
);
assert_eq!(y, 15);
}
#[test]
fn test_ref_result_bi_fold_left() {
use super::bifoldable::explicit::bi_fold_left;
let x: Result<i32, i32> = Ok(5);
let y = bi_fold_left::<RcFnBrand, ResultBrand, _, _, _, _, _>(
(|acc, e: &i32| acc - *e, |acc, s: &i32| acc + *s),
10,
&x,
);
assert_eq!(y, 15);
}
#[test]
fn test_val_result_bi_fold_map() {
use super::bifoldable::explicit::bi_fold_map;
let x: Result<i32, i32> = Ok(5);
let y = bi_fold_map::<RcFnBrand, ResultBrand, _, _, _, _, _>(
(|e: i32| e.to_string(), |s: i32| s.to_string()),
x,
);
assert_eq!(y, "5".to_string());
}
#[test]
fn test_ref_result_bi_fold_map() {
use super::bifoldable::explicit::bi_fold_map;
let x: Result<i32, i32> = Ok(5);
let y = bi_fold_map::<RcFnBrand, ResultBrand, _, _, _, _, _>(
(|e: &i32| e.to_string(), |s: &i32| s.to_string()),
&x,
);
assert_eq!(y, "5".to_string());
}
#[test]
fn test_val_result_bi_traverse() {
use super::bitraversable::explicit::bi_traverse;
let x: Result<i32, i32> = Ok(5);
let y = bi_traverse::<RcFnBrand, ResultBrand, _, _, _, _, OptionBrand, _, _>(
(|e: i32| Some(e + 1), |s: i32| Some(s * 2)),
x,
);
assert_eq!(y, Some(Ok(10)));
}
#[test]
fn test_ref_result_bi_traverse() {
use super::bitraversable::explicit::bi_traverse;
let x: Result<i32, i32> = Ok(5);
let y = bi_traverse::<RcFnBrand, ResultBrand, _, _, _, _, OptionBrand, _, _>(
(|e: &i32| Some(*e + 1), |s: &i32| Some(*s * 2)),
&x,
);
assert_eq!(y, Some(Ok(10)));
}
}