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)) }