1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#![deny(clippy::pedantic)]
#![deny(clippy::all)]
//! Tests if creating a Free Monad for a Vec works. Not sure if this is useful in any way.
//! It is a nice illustration that Free Monads are tree-like though.
use higher::{Apply, Bind, Functor};
use higher_free_macro::free;
free!(FreeVec<A>, Vec<FreeVec<A>>);
//just to appease clippy without disabling the lint....
macro_rules! assert_nearly_equal {
($a:expr, $b:expr, $c:expr) => {
assert!((($a) - ($b)).abs() < $c)
};
}
#[test]
fn test_vector() {
let free_monad = FreeVec::lift_f(vec![2, 3, 4]);
let free_monad_after_fmap = free_monad.fmap(|x| x * 2);
let free_monad_after_bind = free_monad_after_fmap.bind(|x| {
if x % 3 == 0 {
FreeVec::Pure(x)
} else {
FreeVec::lift_f(vec![x, x + 1])
}
});
let functions = FreeVec::lift_f(vec![
(|x| f64::from(x) / 3.0) as fn(u32) -> f64,
(|x| f64::from(x + 2)) as fn(u32) -> f64,
]);
let free_monad_after_apply = free_monad_after_bind.apply(functions.fmap(Into::into));
match free_monad_after_apply {
FreeVec::Free(v) => match &**v {
[FreeVec::Free(left), FreeVec::Free(right)] => {
match &***left {
[FreeVec::Free(left), FreeVec::Pure(middle), FreeVec::Free(right)] => {
match &***left {
[FreeVec::Pure(left), FreeVec::Pure(right)] => {
assert_nearly_equal!(4.0f64 / 3.0f64, *left, f64::EPSILON);
assert_nearly_equal!(5.0f64 / 3.0f64, *right, f64::EPSILON);
}
_ => unreachable!(),
}
assert_nearly_equal!(2.0f64, *middle, f64::EPSILON);
match &***right {
[FreeVec::Pure(left), FreeVec::Pure(right)] => {
assert_nearly_equal!(8.0f64 / 3.0f64, *left, f64::EPSILON);
assert_nearly_equal!(3.0f64, *right, f64::EPSILON);
}
_ => unreachable!(),
}
}
_ => unreachable!(),
}
match &***right {
[FreeVec::Free(left), FreeVec::Pure(middle), FreeVec::Free(right)] => {
match &***left {
[FreeVec::Pure(left), FreeVec::Pure(right)] => {
assert_nearly_equal!(6.0f64, *left, f64::EPSILON);
assert_nearly_equal!(7.0f64, *right, f64::EPSILON);
}
_ => unreachable!(),
}
assert_nearly_equal!(8.0f64, *middle, f64::EPSILON);
match &***right {
[FreeVec::Pure(left), FreeVec::Pure(right)] => {
assert_nearly_equal!(10.0f64, *left, f64::EPSILON);
assert_nearly_equal!(11.0f64, *right, f64::EPSILON);
}
_ => unreachable!(),
}
}
_ => unreachable!(),
}
}
_ => unreachable!(),
},
FreeVec::Pure(_) => unreachable!(),
}
}
|