1
import Foundation
2

3
/// NonEmptyReducible defines a `Reducible` in terms of another type that has an instance of `Foldable` and a method that is able to split a structure of values in a first value and the rest of the values in the structure.
4
public protocol NonEmptyReducible: Reducible {
5
    associatedtype G: Foldable
6

7
    /// Divides a structure of values into a tuple that represents the first value of the structure (first component of the tuple) and the rest of values of the structure (second component of the tuple)
8
    ///
9
    /// - Parameter fa: Structure of values.
10
    /// - Returns: Tuple containing the first and rest of values in the structure.
11
    static func split<A>(_ fa: Kind<Self, A>) -> (A, Kind<G, A>)
12
}
13

14
public extension NonEmptyReducible {
15
    // Docs inherited from `Foldable`
16 0
    static func foldLeft<A, B>(_ fa: Kind<Self, A>, _ b: B, _ f: @escaping (B, A) -> B) -> B {
17 0
        let (a, ga) = split(fa)
18 0
        return G.foldLeft(ga, f(b, a), f)
19
    }
20

21
    // Docs inherited from `Foldable`
22 0
    static func foldRight<A, B>(_ fa: Kind<Self, A>, _ b: Eval<B>, _ f: @escaping (A, Eval<B>) -> Eval<B>) -> Eval<B> {
23 0
        return Eval.fix(Eval<(A, Kind<G, A>)>.always({ self.split(fa) }).flatMap { (a, ga) in f(a, G.foldRight(ga, b, f)) })
24
    }
25

26
    // Docs inherited from `Reducible`
27 0
    static func reduceLeftTo<A, B>(_ fa: Kind<Self, A>, _ f: (A) -> B, _ g: @escaping (B, A) -> B) -> B {
28 0
        let (a, ga) = split(fa)
29 0
        return G.foldLeft(ga, f(a), { b, a in g(b, a) })
30
    }
31

32
    // Docs inherited from `Reducible`
33 0
    static func reduceRightTo<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B, _ g: @escaping (A, Eval<B>) -> Eval<B>) -> Eval<B> {
34 0
        return Eval.fix(Eval.always({ split(fa) }).flatMap { input -> Eval<B> in
35 0
            let (a, ga) = input
36 0
            let evalOpt = G.reduceRightToOption(ga, f, g)
37 0
            let res = evalOpt.flatMap { option in
38 0
                option.fold({ Eval.later({ f(a) })},
39 0
                            { b in g(a, Eval.now(b)) })
40
            }
41 0
            return Eval.fix(res)
42 0
        })
43
    }
44

45
    /// Folds a structure of values provided that its type has an instance of `Monoid`.
46
    ///
47
    /// It uses the monoid empty value as initial value and the combination method for the fold.
48
    ///
49
    /// - Parameter fa: Value to be folded.
50
    /// - Returns: Summary value resulting from the folding process.
51 0
    static func fold<A: Monoid>(_ fa: Kind<Self, A>) -> A {
52 0
        let (a, ga) = split(fa)
53 0
        return a.combine(G.fold(ga))
54
    }
55

56
    /// Looks for an element that matches a given predicate.
57
    ///
58
    /// - Parameters:
59
    ///   - fa: Structure of values where the element matching the predicate needs to be found.
60
    ///   - f: Predicate.
61
    /// - Returns: A value if there is any that matches the predicate, or `Option.none`.
62 0
    static func find<A>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> Bool) -> Option<A> {
63 0
        let (a, ga) = split(fa)
64 0
        return f(a) ? Option.some(a) : G.find(ga, f)
65
    }
66

67
    /// Checks if any element in a structure matches a given predicate.
68
    ///
69
    /// - Parameters:
70
    ///   - fa: Structure of values where the element matching the predicate needs to be found.
71
    ///   - predicate: Predicate.
72
    /// - Returns: A boolean value indicating if any elements in the structure match the predicate.
73 0
    static func exists<A>(_ fa: Kind<Self, A>, _ predicate: @escaping (A) -> Bool) -> Bool {
74 0
        let (a, ga) = split(fa)
75 0
        return predicate(a) || G.exists(ga, predicate)
76
    }
77

78
    /// Checks if all elements in a structure match a given predicate.
79
    ///
80
    /// - Parameters:
81
    ///   - fa: Structure of values where all elements should match the predicate.
82
    ///   - predicate: Predicate.
83
    /// - Returns: A boolean value indicating if all elements in the structure match the predicate.
84 0
    static func forall<A>(_ fa: Kind<Self, A>, _ predicate: @escaping (A) -> Bool) -> Bool {
85 0
        let (a, ga) = split(fa)
86 0
        return predicate(a) && G.forall(ga, predicate)
87
    }
88

89
    /// Counts how many elements a structure contains.
90
    ///
91
    /// - Parameter fa: Structure of values.
92
    /// - Returns: An integer value with the count of how many elements are contained in the structure.
93 0
    static func count<A>(_ fa: Kind<Self, A>) -> Int64 {
94 0
        let (_, tail) = split(fa)
95 0
        return 1 + G.count(tail)
96
    }
97

98
    /// Obtains a specific element of a structure of elements given its indexed position.
99
    ///
100
    /// - Parameters:
101
    ///   - fa: Structure of values.
102
    ///   - index: Indexed position of the element to retrieve.
103
    /// - Returns: A value if there is any at the given position, or `Option.none` otherwise.
104 0
    static func get<A>(_ fa: Kind<Self, A>, _ index: Int64) -> Option<A> {
105 0
        if index == 0 {
106 0
            return Option.some(split(fa).0)
107 0
        } else {
108 0
            return G.get(split(fa).1, index - 1)
109
        }
110
    }
111

112
    /// Performs a monadic left fold from the source context to the target monad.
113
    ///
114
    /// - Parameters:
115
    ///   - fa: Structure of values.
116
    ///   - b: Initial value for the fold.
117
    ///   - f: Folding function.
118
    /// - Returns: Summary value resulting from the folding process in the context of the target monad.
119 0
    static func foldM<H: Monad, A, B>(_ fa: Kind<Self, A>, _ b: B, _ f: @escaping (B, A) -> Kind<H, B>) -> Kind<H, B> {
120 0
        let (a, ga) = split(fa)
121 0
        return H.flatMap(f(b, a), { bb in G.foldM(ga, bb, f)})
122
    }
123
}
124

125
// MARK Syntax for NonEmptyReducible {
126

127
public extension Kind where F: NonEmptyReducible {
128
    /// Divides this structure of values into a tuple that represents the first value of the structure (first component of the tuple) and the rest of values of the structure (second component of the tuple)
129
    ///
130
    /// - Returns: Tuple containing the first and rest of values in the structure.
131 0
    func split() -> (A, Kind<F.G, A>) {
132 0
        return F.split(self)
133
    }
134
}

Read our documentation on viewing source code .

Loading