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
83
84
85
86
87
88
89
90
91
92
93
94
95
use applicative::Applicative;
use functor::Functor;
use kind::{IntoKind, Kind, Reify};
use kinds::OptionKind;
impl Functor<OptionKind> for OptionKind {
fn map<'f_, Fn_, A, B>(a: Kind<'f_, OptionKind, A>, f: Fn_) -> Kind<'f_, OptionKind, B>
where
Fn_: FnOnce(A) -> B + 'f_,
{
a.reify().map(f).into_kind()
}
}
type OptionK<'f_, A> = Kind<'f_, OptionKind, A>;
impl Applicative<OptionKind> for OptionKind {
fn ap<'f_, A, B, Fn_>(fa: OptionK<A>, ff: OptionK<Fn_>) -> OptionK<'f_, B>
where
Fn_: FnOnce(A) -> B,
{
let fa = fa.reify();
let ff = ff.reify();
fa.and_then(|fa| ff.map(|ff| ff(fa))).into_kind()
}
fn point<'f_, A>(a: A) -> Kind<'f_, OptionKind, A> {
Some(a).into_kind()
}
}
#[cfg(test)]
mod tests {
use super::*;
use applicative::{ApplicativeKindExt, Point};
#[test]
fn test_option_pure() {
let f = 5.point::<OptionKind>();
assert_eq!(Some(5), f.reify());
}
fn show_off_kind_tupler<'f_, F_, A, B>(
a: Kind<'f_, F_, A>,
b: Kind<'f_, F_, B>,
) -> Kind<'f_, F_, (A, B)>
where
F_: Applicative<F_>,
{
a.product(b)
}
#[test]
fn test_kind_tupler() {
let a: Kind<OptionKind, i32> = 5.point::<OptionKind>();
let b: Kind<OptionKind, &str> = "rats".point::<OptionKind>();
let ab = show_off_kind_tupler(a, b).reify();
assert_eq!(ab, Some((5, "rats")));
use kinds::IdKind;
let a = 5.point::<IdKind>();
let b = "rats".point::<IdKind>();
let ab = show_off_kind_tupler(a, b).reify().take();
assert_eq!(ab, (5, "rats"));
use kinds::FutureKind;
use futures::future;
use futures::executor::ThreadPool;
use futures::future::FutureResult;
let a = 5.point::<FutureKind>();
let b = "rats".point::<FutureKind>();
let ab = show_off_kind_tupler(a,b).reify();
let ab = ThreadPool::new().unwrap().run(ab).unwrap();
assert_eq!(ab, (5, "rats"))
}
#[test]
fn test_option_product() {
let a = 5.point::<OptionKind>();
let b = "hello".point::<OptionKind>();
let result = a.product(b);
assert_eq!(result.reify(), Some((5, "hello")));
}
}