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
96
97
98
99
100
use std::fmt;
pub mod instr;
use instr::Instr;
mod kleisli;
pub use kleisli::Kleisli;
mod seq;
pub use seq::*;
pub enum Program<'a, I: Instr, A> {
Pure(Box<A>),
Then(Box<I>, Kleisli<'a, I, I::Return, A>)
}
impl<'a, I: 'a + Instr, A> Program<'a, I, A> {
fn and_then_boxed<B, F>(self, js: F) -> Program<'a, I, B>
where F: 'a + Fn(Box<A>) -> Program<'a, I, B> {
match self {
Program::Pure(a) => js(a),
Program::Then(i, is) => Program::Then(i, kleisli::append_boxed(is, js))
}
}
pub fn and_then<B, F>(self, js: F) -> Program<'a, I, B>
where F: 'a + Fn(A) -> Program<'a, I, B> {
match self {
Program::Pure(a) => js(*a),
Program::Then(i, is) => Program::Then(i, is.append(js))
}
}
pub fn map<B, F>(self, f: F) -> Program<'a, I, B>
where F: 'a + Fn(A) -> B {
self.and_then(move |a| point(f(a)))
}
}
impl<'a, I: 'a + Instr, A: PartialEq> PartialEq for Program<'a, I, A> {
fn eq(&self, other: &Program<'a, I, A>) -> bool {
match (self, other) {
(&Program::Pure(ref a), &Program::Pure(ref b)) => a == b,
_ => false
}
}
}
impl<'a, I: 'a + Instr, A: fmt::Debug> fmt::Debug for Program<'a, I, A> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Program::Pure(ref a) => write!(f, "Pure({:?})", a),
&Program::Then(_, _) => write!(f, "Then(..)")
}
}
}
pub fn point<'a, I: 'a + Instr, A>(a: A) -> Program<'a, I, A> {
Program::Pure(Box::new(a))
}
pub fn lift<'a, I: 'a + Instr>(i: I) -> Program<'a, I, I::Return> {
Program::Then(Box::new(i), Kleisli::new())
}