1
import Foundation
2

3
/// A MonadWriter is a `Monad` with the ability to produce a stream of data in addition to the computed values.
4
public protocol MonadWriter: Monad {
5
    /// Type of the side stream of data produced by this monad
6
    associatedtype W
7
    
8
    /// Embeds a writer action.
9
    ///
10
    /// - Parameter aw: A tupe of the writer type and a value.
11
    /// - Returns: The writer action embedded in the context implementing this instance.
12
    static func writer<A>(_ aw: (W, A)) -> Kind<Self, A>
13

14
    /// Adds the side stream of data to the result of a computation.
15
    ///
16
    /// - Parameter fa: A computation.
17
    /// - Returns: The result of the computation paired with the side stream of data.
18
    static func listen<A>(_ fa: Kind<Self, A>) -> Kind<Self, (W, A)>
19

20
    /// Performs a computation and transforms the side stream of data.
21
    ///
22
    /// - Parameter fa: A computation that transform the stream of data.
23
    /// - Returns: Result of the computation.
24
    static func pass<A>(_ fa: Kind<Self, ((W) -> W, A)>) -> Kind<Self, A>
25
}
26

27
public extension MonadWriter {
28
    /// Produces a new value of the side stream of data.
29
    ///
30
    /// - Parameter w: New value.
31
    /// - Returns: Unit.
32 1
    static func tell(_ w: W) -> Kind<Self, ()> {
33 1
        return writer((w, ()))
34
    }
35
    
36
    /// Performs a computation and transforms the side stream of data, pairing it with the result of the computation.
37
    ///
38
    /// - Parameters:
39
    ///   - fa: A computation.
40
    ///   - f: A function to transform the side stream of data.
41
    /// - Returns: A tuple of the transformation of the side stream and the result of the computation.
42 0
    static func listens<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (W) -> B) -> Kind<Self, (B, A)> {
43 0
        return map(listen(fa), { pair in (f(pair.0), pair.1) })
44
    }
45
    
46
    /// Transforms the side stream of data of a given computation.
47
    ///
48
    /// - Parameters:
49
    ///   - fa: A computation.
50
    ///   - f: Transforming function.
51
    /// - Returns: A computation with the same result as the provided one, with the transformed side stream of data.
52 1
    static func censor<A>(_ fa: Kind<Self, A>, _ f: @escaping (W) -> W) -> Kind<Self, A> {
53 1
        return pass(fa.map { a in (f, a) })
54
    }
55
}
56

57
// MARK: Syntax for MonadWriter
58

59
public extension Kind where F: MonadWriter {
60
    /// Embeds a writer action.
61
    ///
62
    /// This is a convenience method to call `MonadWriter.writer` as a static method of this type.
63
    ///
64
    /// - Parameter aw: A tupe of the writer type and a value.
65
    /// - Returns: The writer action embedded in the context implementing this instance.
66 1
    static func writer(_ aw: (F.W, A)) -> Kind<F, A> {
67 1
        return F.writer(aw)
68
    }
69

70
    /// Adds the side stream of data to the result of this computation.
71
    ///
72
    /// This is a convenience method to call `MonadWriter.listen` as an instance method of this type.
73
    ///
74
    /// - Returns: The result of the computation paired with the side stream of data.
75 0
    func listen() -> Kind<F, (F.W, A)> {
76 0
        return F.listen(self)
77
    }
78

79
    /// Performs a computation and transforms the side stream of data.
80
    ///
81
    /// This is a convenience method to call `MonadWriter.pass` as a static method of this type.
82
    ///
83
    /// - Parameter fa: A computation that transform the stream of data.
84
    /// - Returns: Result of the computation.
85 0
    static func pass(_ fa: Kind<F, ((F.W) -> F.W, A)>) -> Kind<F, A> {
86 0
        return F.pass(fa)
87
    }
88

89
    /// Produces a new value of the side stream of data.
90
    ///
91
    /// This is a convenience method to call `MonadWriter.tell` as a static method of this type.
92
    ///
93
    /// - Parameter w: New value.
94
    /// - Returns: Unit.
95 0
    static func tell(_ w: F.W) -> Kind<F, ()> {
96 0
        return F.tell(w)
97
    }
98

99
    /// Performs this computation and transforms the side stream of data, pairing it with the result of this computation.
100
    ///
101
    /// This is a convenience method to call `MonadWriter.listens` as an instance method of this type.
102
    ///
103
    /// - Parameters:
104
    ///   - f: A function to transform the side stream of data.
105
    /// - Returns: A tuple of the transformation of the side stream and the result of the computation.
106 0
    func listens<B>(_ f: @escaping (F.W) -> B) -> Kind<F, (B, A)> {
107 0
        return F.listens(self, f)
108
    }
109

110
    /// Transforms the side stream of data of this computation.
111
    ///
112
    /// This is a convenience method to call `MonadWriter.censor` as an instance method of this type.
113
    ///
114
    /// - Parameters:
115
    ///   - f: Transforming function.
116
    /// - Returns: A computation with the same result as the provided one, with the transformed side stream of data.
117 1
    func censor(_ f: @escaping (F.W) -> F.W) -> Kind<F, A> {
118 1
        return F.censor(self, f)
119
    }
120
}

Read our documentation on viewing source code .

Loading