fp_library/classes/
ref_foldable.rs1#[fp_macros::document_module]
25mod inner {
26 use {
27 crate::{
28 classes::*,
29 kinds::*,
30 types::Endofunction,
31 },
32 fp_macros::*,
33 };
34
35 #[kind(type Of<'a, A: 'a>: 'a;)]
46 pub trait RefFoldable {
47 #[document_signature]
49 #[document_type_parameters(
51 "The lifetime of the elements.",
52 "The brand of the cloneable function to use.",
53 "The type of the elements in the structure.",
54 "The monoid type."
55 )]
56 #[document_parameters(
58 "The function to map each element reference to a monoid.",
59 "The structure to fold."
60 )]
61 #[document_returns("The combined monoid value.")]
63 #[document_examples]
64 fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
78 func: impl Fn(&A) -> M + 'a,
79 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
80 ) -> M
81 where
82 FnBrand: LiftFn + 'a,
83 M: Monoid + 'a, {
84 Self::ref_fold_right::<FnBrand, A, M>(
85 move |a: &A, acc| Semigroup::append(func(a), acc),
86 Monoid::empty(),
87 fa,
88 )
89 }
90
91 #[document_signature]
93 #[document_type_parameters(
95 "The lifetime of the elements.",
96 "The brand of the cloneable function to use.",
97 "The type of the elements in the structure.",
98 "The type of the accumulator."
99 )]
100 #[document_parameters(
102 "The function to apply to each element reference and the accumulator.",
103 "The initial value of the accumulator.",
104 "The structure to fold."
105 )]
106 #[document_returns("The final accumulator value.")]
108 #[document_examples]
109 fn ref_fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
123 func: impl Fn(&A, B) -> B + 'a,
124 initial: B,
125 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
126 ) -> B
127 where
128 FnBrand: LiftFn + 'a, {
129 let f = <FnBrand as LiftFn>::new(move |(a, b): (A, B)| func(&a, b));
130 let m = Self::ref_fold_map::<FnBrand, A, Endofunction<FnBrand, B>>(
131 move |a: &A| {
132 let a = a.clone();
133 let f = f.clone();
134 Endofunction::<FnBrand, B>::new(<FnBrand as LiftFn>::new(move |b| {
135 f((a.clone(), b))
136 }))
137 },
138 fa,
139 );
140 m.0(initial)
141 }
142
143 #[document_signature]
145 #[document_type_parameters(
147 "The lifetime of the elements.",
148 "The brand of the cloneable function to use.",
149 "The type of the elements in the structure.",
150 "The type of the accumulator."
151 )]
152 #[document_parameters(
154 "The function to apply to the accumulator and each element reference.",
155 "The initial value of the accumulator.",
156 "The structure to fold."
157 )]
158 #[document_returns("The final accumulator value.")]
160 #[document_examples]
161 fn ref_fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
175 func: impl Fn(B, &A) -> B + 'a,
176 initial: B,
177 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
178 ) -> B
179 where
180 FnBrand: LiftFn + 'a, {
181 let f = <FnBrand as LiftFn>::new(move |(b, a): (B, A)| func(b, &a));
182 let m = Self::ref_fold_right::<FnBrand, A, Endofunction<FnBrand, B>>(
183 move |a: &A, k: Endofunction<'a, FnBrand, B>| {
184 let a = a.clone();
185 let f = f.clone();
186 let current =
187 Endofunction::<FnBrand, B>::new(<FnBrand as LiftFn>::new(move |b| {
188 f((b, a.clone()))
189 }));
190 Semigroup::append(k, current)
191 },
192 Endofunction::<FnBrand, B>::empty(),
193 fa,
194 );
195 m.0(initial)
196 }
197 }
198}
199
200pub use inner::*;