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
|
#![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_free_macro::free;
use higher::{Functor, Bind, Apply};
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!()
}
}
|