combinator/lib.rs
1//! ## Duo-Combinators
2//! ### Atop
3//! ```
4//! /x:A
5//! M1-D2<
6//! \y:B
7//!
8//! M1.AT(D2) (x,y)
9//! M1: Fn(C)->D
10//! D2: Fn(A,B)->C
11//! ```
12//!
13//! ### Appose
14//! ```
15//! /M2-x:A
16//! D1<
17//! \M2-y:A
18//!
19//! D1.AP(M2) (x,y)
20//! D1: Fn(B,B)->C
21//! M2: Fn(A)->B
22//! ```
23//!
24//! ### Compose
25//! ```
26//! M1-M2-y:B
27//!
28//! M1.CP(M2) (y)
29//! M1: Fn(D)->E
30//! M2: Fn(B)->C
31//! ```
32//!
33//! ### Hook
34//! ```
35//! /x:A
36//! D1<
37//! \M2-y:B
38//!
39//! D1.HK(M2)(x,y)
40//! D1: Fn(A,C)->D
41//! M2: Fn(B)->C
42//! ```
43//!
44//! ### MonoHook
45//! ```
46//! (y)
47//! / \
48//! D1< \
49//! \M2-y:B
50//!
51//! D1.MH(M2)(y)
52//! D1: Fn(B,C)->D
53//! M2: Fn(B)->C
54//! ```
55//! ### RevHook
56//! ```
57//! (y)
58//! / \ /M-x:A
59//! D1< X
60//! \ / \-y:B
61//! (M2(x))
62//!
63//! D1.RH(M2)(x,y)
64//! D1: Fn(B,C)->D
65//! M2: Fn(A)->C
66//! ```
67//! ## Mono-Combinator
68//! ### Relflex
69//! ```
70//! (y)
71//! / \
72//! D1< >y:B
73//! \ /
74//! (y)
75//!
76//! D1.RF()(y)
77//! D1 : (B,B)->C
78//! ```
79//!
80//! ### Flip
81//! ```
82//! (y)
83//! / \ /x:A
84//! D1< X
85//! \ / \y:B
86//! (x)
87//!
88//! D1.FL()(x,y)
89//! D1 : Fn(B,A)->C
90//! ```
91
92
93
94
95pub trait MonoAtop<'a,A,B,C,D> where Self:Sized{
96 #![allow(non_snake_case)]
97 /// ### Atop
98 /// ```
99 /// M1.AT(D2)(x,y)
100 ///
101 /// /x
102 /// M1-D2<
103 /// \y
104 /// ```
105 fn AT<Duo>(self,d: Duo)-> Box<dyn Fn(A,B)->D + 'a>
106 where Self: Fn(C)->D +'a , Duo:Fn(A,B)->C +'a
107 { Box::new(move|x,y|self(d(x,y))) }
108}
109impl<'a,A,B,C,D,Fun> MonoAtop<'a,A,B,C,D> for Fun where Fun: Fn(C)->D {}
110pub trait MonoComposition<'a,B,C,D> where Self: Sized{
111 #![allow(non_snake_case)]
112 /// ### Compose
113 /// ```
114 /// M1.CP(M2)(y)
115 ///
116 /// M1-M2-y
117 /// ```
118 fn CP<Mono2>(self, m2: Mono2)->Box<dyn Fn(B)->D +'a>
119 where Self: Fn(C)->D + 'a, Mono2: Fn(B)->C + 'a
120 { Box::new(move|y|self(m2(y))) }
121}
122impl<'a,B,C,D,Fun> MonoComposition<'a,B,C,D> for Fun where Fun: Fn(C)->D{}
123
124pub trait DuoComposition<'a,A,B,C,D> where Self:Sized{
125 #![allow(non_snake_case)]
126
127 /// ### Hook
128 /// ```
129 /// D1.HK(M2)(x,y)
130 ///
131 /// /x
132 /// D1<
133 /// \M2-y
134 /// ```
135 fn HK<Mono>(self,m:Mono)-> Box<dyn Fn(B,A)->D + 'a>
136 where Self: Fn(B,C)->D + 'a, Mono: Fn(A)->C +'a
137 { Box::new(move|x,y|self(x,m(y))) }
138
139 /// ### RevHook
140 /// ```
141 /// D1.HK(M2)(x,y)
142 ///
143 /// (y)
144 /// / \ /M2-x
145 /// D1< X
146 /// \ / \y
147 /// (M2(x))
148 /// ```
149 fn RH<Mono>(self, m:Mono)-> Box<dyn Fn(A,B)->D + 'a>
150 where Self: Fn(B,C)->D + 'a, Mono: Fn(A)->C + 'a
151 { Box::new(move|x,y|self(y,m(x))) }
152}
153impl<'a,A,B,C,D,Fun> DuoComposition<'a,A,B,C,D> for Fun where Fun: Fn(B,C)->D{}
154
155pub trait DuoFlipMHook<'a,B,C,D> where Self:Sized{
156 #![allow(non_snake_case)]
157 /// ### Flip
158 /// ```
159 /// D1.F()(x,y)
160 ///
161 /// (y)
162 /// / \ /x
163 /// D1< X
164 /// \ / \y
165 /// (x)
166 /// ```
167 fn FL(self)-> Box<dyn Fn(C,B)->D +'a>
168 where Self: Fn(B,C)->D + 'a
169 { Box::new(move|x,y|self(y,x)) }
170
171 /// ### MonoHook
172 /// ```
173 /// D1.MH(M2)(y)
174 ///
175 /// (Y)
176 /// / \
177 /// D1< \
178 /// \M2-y
179 /// ```
180 fn MH<Mono>(self, m: Mono)-> Box<dyn Fn(B)->D +'a>
181 where Self: Fn(B,C)->D + 'a, Mono: Fn(B)->C +'a ,B:Clone
182 { Box::new(move|y|self(y.clone(),m(y))) }
183
184}
185impl<'a,B,C,D,Fun> DuoFlipMHook<'a,B,C,D> for Fun where Fun: Fn(B,C)->D{}
186
187pub trait DuoAppose<'a,A,B,C> where Self:Sized{
188 #![allow(non_snake_case)]
189 /// ### Appose
190 /// ```
191 /// D1.AP(M2)(x,y)
192 ///
193 /// /M2-x:T
194 /// D1<
195 /// \M2-y:T
196 /// ```
197 fn AP<Mono>(self,m:Mono)-> Box<dyn Fn(A,A)->C + 'a>
198 where Self: Fn(B,B)->C +'a, Mono: Fn(A)->B + 'a
199 { Box::new(move|x,y|self( m(x), m(y) ))}
200}
201impl<'a,A,B,C,Fun> DuoAppose<'a,A,B,C> for Fun where Fun: Fn(B,B)->C{}
202
203
204pub trait DuoReflex<'a,B,C> where Self:Sized{
205 #![allow(non_snake_case)]
206 /// reflex
207 /// ```
208 /// D1.RF()(y)
209 ///
210 /// (y)
211 /// / \
212 /// D1< >y
213 /// \ /
214 /// (y)
215 /// ```
216 fn RF(self)-> Box<dyn Fn(B)->C + 'a>
217 where Self: Fn(B,B)->C + 'a, B:Clone
218 { Box::new(move|y| self(y.clone(),y) ) }
219}
220impl<'a,B,C,Fun> DuoReflex<'a,B,C> for Fun where Fun: Fn(B,B)->C{}
221
222
223/// no overhead function composition
224pub fn atop<A,B,C,D,Mono,Duo>(m: Mono,d: Duo)-> impl Fn(A,B)->D
225where Mono: Fn(C)->D, Duo:Fn(A,B)->C
226{ move |x,y|m(d(x,y)) }
227
228pub fn appose<A,B,C,Duo,Mono>(d:Duo,m:Mono)-> impl Fn(A,A)->C
229where Duo: Fn(B,B)->C, Mono: Fn(A)->B
230{ move|x,y|d( m(x), m(y) ) }
231
232pub fn compose<B,C,D,Mono1,Mono2>(m1: Mono1, m2: Mono2)-> impl Fn(B)->D
233where Mono1: Fn(C)->D, Mono2: Fn(B)->C
234{ move|y|m1(m2(y)) }
235
236pub fn hook<A,B,C,D,Duo,Mono>(d:Duo,m:Mono)-> impl Fn(A,B)->D
237where Duo: Fn(A,C)->D, Mono: Fn(B)->C
238{ move|x,y|d(x,m(y)) }
239
240pub fn monohook<B,C,D,Duo,Mono>(d: Duo, m: Mono)-> impl Fn(B)->D
241where Duo: Fn(B,C)->D, Mono: Fn(B)->C, B:Clone
242{ move|y|d(y.clone(),m(y)) }
243
244pub fn revhook<A,B,C,D,Duo,Mono>(d:Duo, m:Mono)-> impl Fn(A,B)->D +
245where Duo: Fn(B,C)->D, Mono: Fn(A)->C
246{ move|x,y|d(y,m(x)) }
247
248pub fn reflex<B,C,Duo>(d:Duo)-> impl Fn(B)->C
249where Duo: Fn(B,B)->C, B:Clone
250{ move|y| d(y.clone(),y) }
251
252pub fn flip<A,B,C,Duo>(d: Duo)-> impl Fn(B,A)->C
253where Duo: Fn(A,B)->C
254{ move|x,y|d(y,x) }
255
256
257#[cfg(test)]
258mod tests {
259 #[test]
260 fn it_works() {
261 }
262}
263
264// implementation references ahead
265
266// fn atop<'a,A,B,C,D,Mono,Duo>(m: Mono,d: Duo)-> Box<dyn Fn(A,B)->D + 'a>
267// where Mono: Fn(C)->D +'a , Duo:Fn(A,B)->C +'a
268// { Box::new(move |x,y|m(d(x,y))) }
269
270// fn appose<'a,A,B,C,Duo,Mono>(d:Duo,m:Mono)-> Box<dyn Fn(A,A)->C + 'a>
271// where Duo: Fn(B,B)->C +'a, Mono: Fn(A)->B + 'a
272// { Box::new(move|x,y|d( m(x), m(y) ))}
273
274// fn compose<'a,B,C,D,Mono1,Mono2>(m1: Mono1, m2: Mono2)->Box<dyn Fn(B)->D +'a>
275// where Mono1: Fn(C)->D + 'a, Mono2: Fn(B)->C + 'a
276// { Box::new(move|y|m1(m2(y))) }
277
278// fn hook<'a,A,B,C,D,Duo,Mono>(d:Duo,m:Mono)-> Box<dyn Fn(A,B)->D + 'a>
279// where Duo: Fn(A,C)->D + 'a, Mono: Fn(B)->C +'a
280// { Box::new(move|x,y|d(x,m(y))) }
281
282// fn monohook<'a,B,C,D,Duo,Mono>(d: Duo, m: Mono)-> Box<dyn Fn(B)->D +'a>
283// where Duo: Fn(B,C)->D + 'a, Mono: Fn(B)->C +'a ,B:Clone
284// { Box::new(move|y|d(y.clone(),m(y))) }
285
286// fn revhook<'a,A,B,C,D,Duo,Mono>(d:Duo, m:Mono)-> Box<dyn Fn(A,B)->D + 'a>
287// where Duo: Fn(B,C)->D + 'a, Mono: Fn(A)->C + 'a
288// { Box::new(move|x,y|d(y,m(x))) }
289
290// fn reflex<'a,B,C,Duo>(d:Duo)-> Box<dyn Fn(B)->C + 'a>
291// where Duo: Fn(B,B)->C + 'a, B:Clone
292// { Box::new(move|y| d(y.clone(),y) ) }
293
294// fn flip<'a,A,B,C,Duo>(d: Duo)-> Box<dyn Fn(B,A)->C +'a>
295// where Duo: Fn(A,B)->C + 'a
296// { Box::new(move|x,y|d(y,x)) }