1
import Foundation
2

3
/// Foldable describes types that have the ability to be folded to a summary value.
4
public protocol Foldable {
5
    /// Eagerly folds a value to a summary value from left to right.
6
    ///
7
    /// - Parameters:
8
    ///   - fa: Value to be folded.
9
    ///   - b: Initial value for the folding process.
10
    ///   - f: Folding function.
11
    /// - Returns: Summary value resulting from the folding process.
12
    static func foldLeft<A, B>(_ fa: Kind<Self, A>, _ b: B, _ f: @escaping (B, A) -> B) -> B
13

14
    /// Lazily folds a value to a summary value from right to left.
15
    ///
16
    /// - Parameters:
17
    ///   - fa: Value to be folded.
18
    ///   - b: Initial value for the folding process.
19
    ///   - f: Folding function.
20
    /// - Returns: Summary value resulting from the folding process.
21
    static func foldRight<A, B>(_ fa: Kind<Self, A>, _ b: Eval<B>, _ f: @escaping (A, Eval<B>) -> Eval<B>) -> Eval<B>
22
}
23

24
public extension Foldable {
25
    /// Folds a structure of values provided that its type has an instance of `Monoid`.
26
    ///
27
    /// It uses the monoid empty value as initial value and the combination method for the fold.
28
    ///
29
    /// - Parameter fa: Value to be folded.
30
    /// - Returns: Summary value resulting from the folding process.
31 0
    static func fold<A: Monoid>(_ fa : Kind<Self, A>) -> A {
32 0
        return foldLeft(fa, A.empty(), { acc, a in acc.combine(a) })
33
    }
34

35
    /// Reduces the elements of a structure down to a single value by applying the provided transformation and aggregation funtions in a left-associative manner.
36
    ///
37
    /// - Parameters:
38
    ///   - fa: Value to be folded.
39
    ///   - f: Transforming function.
40
    ///   - g: Folding function.
41
    /// - Returns: Optional summary value resulting from the folding process. It will be an `Option.none` if the structure is empty, or a value if not.
42 0
    static func reduceLeftToOption<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B, _ g: @escaping (B, A) -> B) -> Option<B> {
43 0
        return Option.fix(foldLeft(fa, Option.empty, { option, a in
44 0
            Option.fix(option).fold(constant(Option.some(f(a))),
45 0
                                    { b in Option.some(g(b, a)) })
46 0
        }))
47
    }
48

49
    /// Reduces the elements of a structure down to a single value by applying the provided transformation and aggregation functions in a right-associative manner.
50
    ///
51
    /// - Parameters:
52
    ///   - fa: Value to be folded.
53
    ///   - f: Transforming function.
54
    ///   - g: Folding function.
55
    /// - Returns: Optional summary value resulting from the folding process. It will be an `Option.none` if the structure is empty, or a value if not.
56 0
    static func reduceRightToOption<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B, _ g: @escaping (A, Eval<B>) -> Eval<B>) -> Eval<Option<B>> {
57 0
        return Eval.fix(foldRight(fa, Eval.now(Option.empty), { a, lb in
58 0
            Eval.fix(Eval.fix(lb).flatMap({ option in
59 0
                Option.fix(option).fold({ Eval.later({ Option.some(f(a)) }) },
60 0
                                        { b in Eval.fix(g(a, Eval.now(b)).map(Option.some)) })
61 0
            }))
62 0
        }).map { x in Option.fix(x) })
63
    }
64

65
    /// Reduces the elements of a structure down to a single value by applying the provided aggregation function in a left-associative manner.
66
    ///
67
    /// - Parameters:
68
    ///   - fa: Value to be folded.
69
    ///   - f: Folding function.
70
    /// - Returns: Optional summary value resulting from the folding process.
71 0
    static func reduceLeftOption<A>(_ fa: Kind<Self, A>, _ f: @escaping (A, A) -> A) -> Option<A> {
72 0
        return reduceLeftToOption(fa, id, f)
73
    }
74

75
    /// Reduces the elements of a structure down to a single value by applying the provided aggregation function in a right-associative manner.
76
    ///
77
    /// - Parameters:
78
    ///   - fa: Value to be folded.
79
    ///   - f: Folding function.
80
    /// - Returns: Optional summary value resulting from the folding process.
81 0
    static func reduceRightOption<A>(_ fa: Kind<Self, A>, _ f: @escaping (A, Eval<A>) -> Eval<A>) -> Eval<Option<A>> {
82 0
        return reduceRightToOption(fa, id, f)
83
    }
84

85
    /// Folds a structure of values provided that its type has an instance of `Monoid`.
86
    ///
87
    /// It uses the monoid empty value as initial value and the combination method for the fold.
88
    ///
89
    /// - Parameter fa: Value to be folded.
90
    /// - Returns: Summary value resulting from the folding process.
91 0
    static func combineAll<A: Monoid>(_ fa: Kind<Self, A>) -> A {
92 0
        return fold(fa)
93
    }
94

95
    /// Transforms the elements of a structure to a type with a `Monoid` instance and folds them using the empty and combine methods of such `Monoid` instance.
96
    ///
97
    /// - Parameters:
98
    ///   - fa: Value to be transformed and folded.
99
    ///   - f: Transforming function.
100
    /// - Returns: Summary value resulting from the transformation and folding process.
101 1
    static func foldMap<A, B: Monoid>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B) -> B {
102 1
        return foldLeft(fa, B.empty(), { b, a in b.combine(f(a)) })
103
    }
104

105
    /// Traverses a structure of values, transforming them with a provided function and discarding the result of its effect.
106
    ///
107
    /// - Parameters:
108
    ///   - fa: Structure of values.
109
    ///   - f: Transforming function.
110
    /// - Returns: Unit in the context of the effect of the result of the transforming function.
111 0
    static func traverse_<G: Applicative, A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> Kind<G, B>) -> Kind<G, Unit> {
112 0
        return foldRight(fa, Eval.always({ G.pure(unit) }), { a, acc in
113 0
            G.map2Eval(f(a), acc, { _, _ in unit })
114 0
        }).value()
115
    }
116

117
    /// Traverses a structure of effects, performing them and discarding their result.
118
    ///
119
    /// - Parameter fga: Structure of effects.
120
    /// - Returns: Unit in the context of the effects contained in the structure.
121 0
    static func sequence_<G: Applicative, A>(_ fga: Kind<Self, Kind<G, A>>) -> Kind<G, Unit> {
122 0
        return traverse_(fga, id)
123
    }
124

125
    /// Looks for an element that matches a given predicate.
126
    ///
127
    /// - Parameters:
128
    ///   - fa: Structure of values where the element matching the predicate needs to be found.
129
    ///   - f: Predicate.
130
    /// - Returns: A value if there is any that matches the predicate, or `Option.none`.
131 1
    static func find<A>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> Bool) -> Option<A> {
132 1
        return foldRight(fa, Eval.now(Option.none()), { a, lb in
133 1
            f(a) ? Eval.now(Option.some(a)) : lb
134 1
        }).value()
135
    }
136

137
    /// Checks if any element in a structure matches a given predicate.
138
    ///
139
    /// - Parameters:
140
    ///   - fa: Structure of values where the element matching the predicate needs to be found.
141
    ///   - predicate: Predicate.
142
    /// - Returns: A boolean value indicating if any elements in the structure match the predicate.
143 1
    static func exists<A>(_ fa: Kind<Self, A>, _ predicate: @escaping (A) -> Bool) -> Bool {
144 1
        return foldRight(fa, Eval.false, { a, lb in
145 1
            predicate(a) ? Eval.true : lb
146 1
        }).value()
147
    }
148

149
    /// Checks if all elements in a structure match a given predicate.
150
    ///
151
    /// - Parameters:
152
    ///   - fa: Structure of values where all elements should match the predicate.
153
    ///   - predicate: Predicate.
154
    /// - Returns: A boolean value indicating if all elements in the structure match the predicate.
155 1
    static func forall<A>(_ fa: Kind<Self, A>, _ predicate: @escaping (A) -> Bool) -> Bool {
156 1
        return foldRight(fa, Eval.true, { a, lb in
157 1
            predicate(a) ? lb : Eval.false
158 1
        }).value()
159
    }
160

161
    /// Checks if a structure of values is empty.
162
    ///
163
    /// - Parameter fa: Structure of values.
164
    /// - Returns: `false` if the structure contains any value, `true` otherwise.
165 1
    static func isEmpty<A>(_ fa: Kind<Self, A>) -> Bool {
166 1
        return foldRight(fa, Eval.true, { _, _ in Eval.false }).value()
167
    }
168

169
    /// Checks if a structure of values is not empty.
170
    ///
171
    /// - Parameter fa: Structure of values.
172
    /// - Returns: `true` if the structure contains any value, `false` otherwise.
173 0
    static func nonEmpty<A>(_ fa: Kind<Self, A>) -> Bool {
174 0
        return !isEmpty(fa)
175
    }
176

177
    /// Performs a monadic left fold from the source context to the target monad.
178
    ///
179
    /// - Parameters:
180
    ///   - fa: Structure of values.
181
    ///   - b: Initial value for the fold.
182
    ///   - f: Folding function.
183
    /// - Returns: Summary value resulting from the folding process in the context of the target monad.
184 1
    static func foldM<G: Monad, A, B>(_ fa: Kind<Self, A>, _ b: B, _ f: @escaping (B, A) -> Kind<G, B>) -> Kind<G, B> {
185 1
        return foldLeft(fa, G.pure(b), { gb, a in G.flatMap(gb, { b in f(b, a) }) })
186
    }
187

188
    /// Performs a monadic left fold by mapping the values in a structure to ones in the target monad context and using the `Monoid` instance to combine them.
189
    ///
190
    /// - Parameters:
191
    ///   - fa: Structure of values.
192
    ///   - f: Trasnforming function.
193
    /// - Returns: Summary value resulting from the transformation and folding process in the context of the target monad.
194 0
    static func foldMapM<G: Monad, A, B: Monoid>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> Kind<G, B>) -> Kind<G, B> {
195 0
        return foldM(fa, B.empty(), { b, a in G.map(f(a), { bb in b.combine(bb) }) })
196
    }
197

198
    /// Obtains a specific element of a structure of elements given its indexed position.
199
    ///
200
    /// - Parameters:
201
    ///   - fa: Structure of values.
202
    ///   - index: Indexed position of the element to retrieve.
203
    /// - Returns: A value if there is any at the given position, or `Option.none` otherwise.
204 0
    static func get<A>(_ fa: Kind<Self, A>, _ index: Int64) -> Option<A> {
205 0
        return Either.fix(foldM(fa, Int64(0), { i, a in
206 0
            (i == index) ?
207 0
                Either<A, Int64>.left(a) :
208 0
                Either<A, Int64>.right(i + 1)
209 0
        })).fold(Option<A>.some,
210 0
                 constant(Option<A>.none()))
211
    }
212

213
    /// Counts how many elements a structure contains.
214
    ///
215
    /// - Parameter fa: Structure of values.
216
    /// - Returns: An integer value with the count of how many elements are contained in the structure.
217 1
    static func count<A>(_ fa: Kind<Self, A>) -> Int64 {
218 1
        return foldMap(fa, constant(1))
219
    }
220
    
221 1
    static func foldK<A, G: MonoidK>(_ fga: Kind<Self, Kind<G, A>>) -> Kind<G, A> {
222 1
        return reduceK(fga)
223
    }
224
    
225 1
    static func reduceK<A, G: MonoidK>(_ fga: Kind<Self, Kind<G, A>>) -> Kind<G, A> {
226 1
        return foldLeft(fga, Kind<G, A>.emptyK(), { b, a in b.combineK(a) })
227
    }
228
}
229

230
// MARK: Syntax for Foldable
231

232
public extension Kind where F: Foldable {
233
    /// Eagerly folds this value to a summary value from left to right.
234
    ///
235
    /// - Parameters:
236
    ///   - b: Initial value for the folding process.
237
    ///   - f: Folding function.
238
    /// - Returns: Summary value resulting from the folding process.
239 1
    func foldLeft<B>(_ b: B, _ f: @escaping (B, A) -> B) -> B {
240 1
        return F.foldLeft(self, b, f)
241
    }
242

243
    /// Lazily folds this value to a summary value from right to left.
244
    ///
245
    /// - Parameters:
246
    ///   - b: Initial value for the folding process.
247
    ///   - f: Folding function.
248
    /// - Returns: Summary value resulting from the folding process.
249 1
    func foldRight<B>(_ b: Eval<B>, _ f: @escaping (A, Eval<B>) -> Eval<B>) -> Eval<B> {
250 1
        return F.foldRight(self, b, f)
251
    }
252

253
    /// Reduces the elements of this structure down to a single value by applying the provided transformation and aggregation funtions in a left-associative manner.
254
    ///
255
    /// - Parameters:
256
    ///   - f: Transforming function.
257
    ///   - g: Folding function.
258
    /// - Returns: Optional summary value resulting from the folding process. It will be an `Option.none` if the structure is empty, or a value if not.
259 0
    func reduceLeftToOption<B>(_ f: @escaping (A) -> B, _ g: @escaping (B, A) -> B) -> Option<B> {
260 0
        return F.reduceLeftToOption(self, f, g)
261
    }
262

263
    /// Reduces the elements of this structure down to a single value by applying the provided transformation and aggregation functions in a right-associative manner.
264
    ///
265
    /// - Parameters:
266
    ///   - f: Transforming function.
267
    ///   - g: Folding function.
268
    /// - Returns: Optional summary value resulting from the folding process. It will be an `Option.none` if the structure is empty, or a value if not.
269 0
    func reduceRightToOption<B>(_ f: @escaping (A) -> B, _ g: @escaping (A, Eval<B>) -> Eval<B>) -> Eval<Option<B>> {
270 0
        return F.reduceRightToOption(self, f, g)
271
    }
272

273
    /// Reduces the elements of this structure down to a single value by applying the provided aggregation function in a left-associative manner.
274
    ///
275
    /// - Parameters:
276
    ///   - f: Folding function.
277
    /// - Returns: Optional summary value resulting from the folding process.
278 0
    func reduceLeftOption(_ f: @escaping (A, A) -> A) -> Option<A> {
279 0
        return F.reduceLeftOption(self, f)
280
    }
281

282
    /// Reduces the elements of this structure down to a single value by applying the provided aggregation function in a right-associative manner.
283
    ///
284
    /// - Parameters:
285
    ///   - f: Folding function.
286
    /// - Returns: Optional summary value resulting from the folding process.
287 0
    func reduceRightOption(_ f: @escaping (A, Eval<A>) -> Eval<A>) -> Eval<Option<A>> {
288 0
        return F.reduceRightOption(self, f)
289
    }
290
    
291
    /// Transforms the elements of this structure to a type with a `Monoid` instance and folds them using the empty and combine methods of such `Monoid` instance.
292
    ///
293
    /// - Parameters:
294
    ///   - fa: Value to be transformed and folded.
295
    ///   - f: Transforming function.
296
    /// - Returns: Summary value resulting from the transformation and folding process.
297 1
    func foldMap<B: Monoid>(_ f: @escaping (A) -> B) -> B {
298 1
        return F.foldMap(self, f)
299
    }
300

301
    /// Traverses this structure of values, transforming them with a provided function and discarding the result of its effect.
302
    ///
303
    /// - Parameters:
304
    ///   - f: Transforming function.
305
    /// - Returns: Unit in the context of the effect of the result of the transforming function.
306 0
    func traverse_<G: Applicative, B>(_ f: @escaping (A) -> Kind<G, B>) -> Kind<G, Unit> {
307 0
        return F.traverse_(self, f)
308
    }
309

310
    /// Traverses this structure of effects, performing them and discarding their result.
311
    ///
312
    /// - Returns: Unit in the context of the effects contained in the structure.
313 0
    func sequence_<G: Applicative, AA>() -> Kind<G, Unit> where A == Kind<G, AA> {
314 0
        return F.sequence_(self)
315
    }
316

317
    /// Looks for an element that matches a given predicate.
318
    ///
319
    /// - Parameters:
320
    ///   - f: Predicate.
321
    /// - Returns: A value if there is any that matches the predicate, or `Option.none`.
322 0
    func find(_ f: @escaping (A) -> Bool) -> Option<A> {
323 0
        return F.find(self, f)
324
    }
325

326
    /// Checks if any element in this structure matches a given predicate.
327
    ///
328
    /// - Parameters:
329
    ///   - predicate: Predicate.
330
    /// - Returns: A boolean value indicating if any elements in the structure match the predicate.
331 1
    func exists(_ predicate: @escaping (A) -> Bool) -> Bool {
332 1
        return F.exists(self, predicate)
333
    }
334

335
    /// Checks if all elements in this structure match a given predicate.
336
    ///
337
    /// - Parameters:
338
    ///   - predicate: Predicate.
339
    /// - Returns: A boolean value indicating if all elements in the structure match the predicate.
340 1
    func forall(_ predicate: @escaping (A) -> Bool) -> Bool {
341 1
        return F.forall(self, predicate)
342
    }
343

344
    /// Checks if this structure of values is empty.
345
    ///
346
    /// - Returns: `false` if the structure contains any value, `true` otherwise.
347 1
    var isEmpty: Bool {
348 1
        return F.isEmpty(self)
349
    }
350

351
    /// Checks if this structure of values is not empty.
352
    ///
353
    /// - Returns: `true` if the structure contains any value, `false` otherwise.
354 0
    var nonEmpty: Bool {
355 0
        return F.nonEmpty(self)
356
    }
357

358
    /// Performs a monadic left fold from the source context to the target monad.
359
    ///
360
    /// - Parameters:
361
    ///   - b: Initial value for the fold.
362
    ///   - f: Folding function.
363
    /// - Returns: Summary value resulting from the folding process in the context of the target monad.
364 0
    func foldM<G: Monad, B>(_ b: B, _ f: @escaping (B, A) -> Kind<G, B>) -> Kind<G, B> {
365 0
        return F.foldM(self, b, f)
366
    }
367

368
    /// Performs a monadic left fold by mapping the values in this structure to ones in the target monad context and using the `Monoid` instance to combine them.
369
    ///
370
    /// - Parameters:
371
    ///   - f: Trasnforming function.
372
    /// - Returns: Summary value resulting from the transformation and folding process in the context of the target monad.
373 0
    func foldMapM<G: Monad, B: Monoid>(_ f: @escaping (A) -> Kind<G, B>) -> Kind<G, B> {
374 0
        return F.foldMapM(self, f)
375
    }
376

377
    /// Obtains a specific element of a structure of elements given its indexed position.
378
    ///
379
    /// - Parameters:
380
    ///   - index: Indexed position of the element to retrieve.
381
    /// - Returns: A value if there is any at the given position, or `Option.none` otherwise.
382 0
    func get(_ index: Int64) -> Option<A> {
383 0
        return F.get(self, index)
384
    }
385

386
    /// Counts how many elements this structure contains.
387
    ///
388
    /// - Returns: An integer value with the count of how many elements are contained in the structure.
389 1
    var count: Int64 {
390 1
        return F.count(self)
391
    }
392
    
393 1
    func foldK<G: MonoidK, B>() -> Kind<G, B> where A == Kind<G, B> {
394 1
        return F.foldK(self)
395
    }
396
    
397 0
    func reduceK<G: MonoidK, B>() -> Kind<G, B> where A == Kind<G, B> {
398 0
        return F.reduceK(self)
399
    }
400
}
401

402
public extension Kind where F: Foldable, A: Monoid {
403
    /// Folds this structure of values provided that its type has an instance of `Monoid`.
404
    ///
405
    /// It uses the monoid empty value as initial value and the combination method for the fold.
406
    ///
407
    /// - Returns: Summary value resulting from the folding process.
408 0
    func fold() -> A {
409 0
        return F.fold(self)
410
    }
411

412
    /// Folds this structure of values provided that its type has an instance of `Monoid`.
413
    ///
414
    /// It uses the monoid empty value as initial value and the combination method for the fold.
415
    ///
416
    /// - Returns: Summary value resulting from the folding process.
417 0
    func combineAll() -> A {
418 0
        return F.combineAll(self)
419
    }
420
}

Read our documentation on viewing source code .

Loading