aboutsummaryrefslogtreecommitdiff
path: root/tests/vector.rs
blob: 2b2f4b2071c00dece6dc291c4b6465bf223ce496 (plain) (blame)
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!()
    }
}