1
import Foundation
2

3
/// Reducible augments the functions provided by `Foldable` with reducing functions that do not need an initial value.
4
public protocol Reducible: Foldable {
5
    /// Eagerly reduces a structure of values from left to right, also performing a transformation of values.
6
    ///
7
    /// - Parameters:
8
    ///   - fa: Structure of values.
9
    ///   - f: Transforming function.
10
    ///   - g: Folding function.
11
    /// - Returns: Summary value of this reduction.
12
    static func reduceLeftTo<A, B>(_ fa : Kind<Self, A>, _ f : (A) -> B, _ g : (B, A) -> B) -> B
13
    
14
    /// Lazily reduces a structure of values from right to left, also performing a transformation of values.
15
    ///
16
    /// - Parameters:
17
    ///   - fa: Structure of values.
18
    ///   - f: Transforming function.
19
    ///   - g: Folding function.
20
    /// - Returns: Potentially lazy summary value of this reduction.
21
    static func reduceRightTo<A, B>(_ fa : Kind<Self, A>, _ f : (A) -> B, _ g : (A, Eval<B>) -> Eval<B>) -> Eval<B>
22
}
23

24
// MARK: Related methods
25

26
public extension Reducible {
27
    /// Eagerly reduces a structure of values from left to right without transforming them.
28
    ///
29
    /// - Parameters:
30
    ///   - fa: Structure of values.
31
    ///   - f: Folding function.
32
    /// - Returns: Summary value of this reduction.
33 0
    static func reduceLeft<A>(_ fa : Kind<Self, A>, _ f : (A, A) -> A) -> A {
34 0
        return reduceLeftTo(fa, id, f)
35
    }
36

37
    /// Lazily reduces a structure of values from right to left without transforming them.
38
    ///
39
    /// - Parameters:
40
    ///   - fa: Structure of values.
41
    ///   - f: Folding function.
42
    /// - Returns: Potentially lazy summary value of this reduction.
43 0
    static func reduceRight<A>(_ fa : Kind<Self, A>, _ f : (A, Eval<A>) -> Eval<A>) -> Eval<A> {
44 0
        return reduceRightTo(fa, id, f)
45
    }
46

47
    /// Reduces the elements of a structure down to a single value by applying the provided transformation and aggregation funtions in a left-associative manner.
48
    ///
49
    /// - Parameters:
50
    ///   - fa: Value to be folded.
51
    ///   - f: Transforming function.
52
    ///   - g: Folding function.
53
    /// - 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.
54 0
    static func reduceLeftToOption<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B, _ g: @escaping (B, A) -> B) -> Option<B> {
55 0
        return Option<B>.some(reduceLeftTo(fa, f, g))
56
    }
57

58
    /// Reduces the elements of a structure down to a single value by applying the provided transformation and aggregation functions in a right-associative manner.
59
    ///
60
    /// - Parameters:
61
    ///   - fa: Value to be folded.
62
    ///   - f: Transforming function.
63
    ///   - g: Folding function.
64
    /// - 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.
65 0
    static func reduceRightToOption<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B, _ g: @escaping (A, Eval<B>) -> Eval<B>) -> Eval<Option<B>> {
66 0
        return Eval<Option<B>>.fix(reduceRightTo(fa, f, g).map(Option<B>.some))
67
    }
68

69
    /// Checks if a structure of values is empty.
70
    ///
71
    /// An instance of `Reducible` is never empty.
72
    ///
73
    /// - Parameter fa: Structure of values.
74
    /// - Returns: `false` if the structure contains any value, `true` otherwise.
75 0
    static func isEmpty<A>(_ fa: Kind<Self, A>) -> Bool {
76 0
        return false
77
    }
78

79
    /// Checks if a structure of values is not empty.
80
    ///
81
    /// An instance of `Reducible` is always non-empty.
82
    ///
83
    /// - Parameter fa: Structure of values.
84
    /// - Returns: `true` if the structure contains any value, `false` otherwise.
85 0
    static func nonEmpty<A>(_ fa: Kind<Self, A>) -> Bool {
86 0
        return true
87
    }
88

89
    /// Reduces a structure of values to a summary value using the combination capabilities of the `Semigroup` instance of the underlying type.
90
    ///
91
    /// - Parameter fa: Structure of values.
92
    /// - Returns: Summary value of this reduction.
93 0
    static func reduce<A: Semigroup>(_ fa: Kind<Self, A>) -> A {
94 0
        return reduceLeft(fa, { b, a in a.combine(b) })
95
    }
96

97
    /// Reduces a structure of values by mapping them to a type with a `Semigroup` instance, and using its combination capabilities.
98
    ///
99
    /// - Parameters:
100
    ///   - fa: Structure of values.
101
    ///   - f: Mapping function.
102
    /// - Returns: Summary value of this reduction.
103 0
    static func reduceMap<A, B: Semigroup>(_ fa: Kind<Self, A>, _ f: (A) -> B) -> B {
104 0
        return reduceLeftTo(fa, f, { b, a in b.combine(f(a)) })
105
    }
106
}
107

108
// MARK: Syntax for Reducible
109

110
public extension Kind where F: Reducible {
111
    /// Eagerly reduces this structure of values from left to right, also performing a transformation of values.
112
    ///
113
    /// - Parameters:
114
    ///   - f: Transforming function.
115
    ///   - g: Folding function.
116
    /// - Returns: Summary value of this reduction.
117 0
    func reduceLeftTo<B>(_ f: (A) -> B, _ g: (B, A) -> B) -> B {
118 0
        return F.reduceLeftTo(self, f, g)
119
    }
120

121
    /// Lazily reduces this structure of values from right to left, also performing a transformation of values.
122
    ///
123
    /// - Parameters:
124
    ///   - f: Transforming function.
125
    ///   - g: Folding function.
126
    /// - Returns: Potentially lazy summary value of this reduction.
127 0
    func reduceRightTo<B>(_ f : (A) -> B, _ g : (A, Eval<B>) -> Eval<B>) -> Eval<B> {
128 0
        return F.reduceRightTo(self, f, g)
129
    }
130

131
    /// Reduces this structure of values by mapping them to a type with a `Semigroup` instance, and using its combination capabilities.
132
    ///
133
    /// - Parameters:
134
    ///   - f: Mapping function.
135
    /// - Returns: Summary value of this reduction.
136 0
    func reduceMap<B: Semigroup>(_ f : (A) -> B) -> B {
137 0
        return F.reduceMap(self, f)
138
    }
139
}
140

141
public extension Kind where F: Reducible, A: Semigroup {
142
    /// Reduces this structure of values to a summary value using the combination capabilities of the `Semigroup` instance of the underlying type.
143
    ///
144
    /// - Returns: Summary value of this reduction.
145 0
    func reduce() -> A {
146 0
        return F.reduce(self)
147
    }
148
}

Read our documentation on viewing source code .

Loading