1use std::rc::Rc;
2
3pub fn flip<A, B, C>(f: Rc<dyn Fn(A) -> Rc<dyn Fn(B) -> C>>) -> Rc<dyn Fn(B) -> Rc<dyn Fn(A) -> C>>
5where
6 A: Clone + 'static,
7 B: Clone + 'static,
8 C: 'static,
9{
10 Rc::new(move |b: B| {
11 let f = f.clone();
12 Rc::new(move |a: A| f(a.clone())(b.clone()))
13 })
14}
15
16pub fn flip0<A, B>(f: Rc<dyn Fn(A) -> Rc<dyn Fn() -> B>>) -> Rc<dyn Fn() -> Rc<dyn Fn(A) -> B>>
18where
19 A: Clone + 'static,
20 B: 'static,
21{
22 Rc::new(move || {
23 let f = f.clone();
24 Rc::new(move |a: A| f(a.clone())())
25 })
26}
27
28pub fn flip2<A, B, C, D>(
30 f: Rc<dyn Fn(A) -> Rc<dyn Fn((B, C)) -> D>>,
31) -> Rc<dyn Fn((B, C)) -> Rc<dyn Fn(A) -> D>>
32where
33 A: Clone + 'static,
34 B: Clone + 'static,
35 C: Clone + 'static,
36 D: 'static,
37{
38 Rc::new(move |bc: (B, C)| {
39 let f = f.clone();
40 Rc::new(move |a: A| f(a.clone())(bc.clone()))
41 })
42}
43
44pub fn flip3<A, B, C, D, E>(
46 f: Rc<dyn Fn(A) -> Rc<dyn Fn((B, C, D)) -> E>>,
47) -> Rc<dyn Fn((B, C, D)) -> Rc<dyn Fn(A) -> E>>
48where
49 A: Clone + 'static,
50 B: Clone + 'static,
51 C: Clone + 'static,
52 D: Clone + 'static,
53 E: 'static,
54{
55 Rc::new(move |bcd: (B, C, D)| {
56 let f = f.clone();
57 Rc::new(move |a: A| f(a.clone())(bcd.clone()))
58 })
59}
60
61pub fn flip4<A, B, C, D, E, F>(
63 f: Rc<dyn Fn(A) -> Rc<dyn Fn((B, C, D, E)) -> F>>,
64) -> Rc<dyn Fn((B, C, D, E)) -> Rc<dyn Fn(A) -> F>>
65where
66 A: Clone + 'static,
67 B: Clone + 'static,
68 C: Clone + 'static,
69 D: Clone + 'static,
70 E: Clone + 'static,
71 F: 'static,
72{
73 Rc::new(move |bcde: (B, C, D, E)| {
74 let f = f.clone();
75 Rc::new(move |a: A| f(a.clone())(bcde.clone()))
76 })
77}
78
79pub fn flip5<A, B, C, D, E, F, G>(
81 f: Rc<dyn Fn(A) -> Rc<dyn Fn((B, C, D, E, F)) -> G>>,
82) -> Rc<dyn Fn((B, C, D, E, F)) -> Rc<dyn Fn(A) -> G>>
83where
84 A: Clone + 'static,
85 B: Clone + 'static,
86 C: Clone + 'static,
87 D: Clone + 'static,
88 E: Clone + 'static,
89 F: Clone + 'static,
90 G: 'static,
91{
92 Rc::new(move |bcdef: (B, C, D, E, F)| {
93 let f = f.clone();
94 Rc::new(move |a: A| f(a.clone())(bcdef.clone()))
95 })
96}
97
98#[test]
99fn test_tall_flip() {
100 fn base(a: i32) -> Rc<dyn Fn(i32) -> i32> {
101 Rc::new(move |b| a + b)
102 }
103
104 let f = Rc::new(base);
105 let mut flipped = flip(f);
106
107 for i in 0..1000 {
108 flipped = flip(flipped);
109 }
110
111 let inner = flipped(1);
112 assert_eq!(inner(2), 3);
113}
114
115pub fn flip_throw<A, B, C, E>(
116 f: Rc<dyn Fn(A) -> Rc<dyn Fn(B) -> Result<C, E>>>,
117) -> Rc<dyn Fn(B) -> Rc<dyn Fn(A) -> Result<C, E>>>
118where
119 A: Clone + 'static,
120 B: Clone + 'static,
121 C: 'static,
122 E: 'static,
123{
124 Rc::new(move |b: B| {
125 let f = f.clone();
126 Rc::new(move |a: A| f(a.clone())(b.clone()))
127 })
128}
129
130#[macro_export]
131macro_rules! flip_macro {
132 ($f:expr) => {
133 $crate::flip(Rc::new($f))
134 };
135}