1
import Foundation
2

3
/// A MonadState is a `Monad` that maintains a state.
4
public protocol MonadState: Monad {
5
    /// Type of the state maintained in this instance
6
    associatedtype S
7

8
    /// Retrieves the state from the internals of the monad.
9
    ///
10
    /// - Returns: Maintained state.
11
    static func get() -> Kind<Self, S>
12

13
    /// Replaces the state inside the monad.
14
    ///
15
    /// - Parameter s: New state.
16
    /// - Returns: Unit.
17
    static func set(_ s: S) -> Kind<Self, ()>
18
}
19

20
public extension MonadState {
21
    /// Embeds a state action into the monad.
22
    ///
23
    /// - Parameter f: A function that receives the state and computes a value and a new state.
24
    /// - Returns: A value with the output of the function and the new state.
25 0
    static func state<A>(_ f: @escaping (S) -> (S, A)) -> Kind<Self, A> {
26 0
        return flatMap(get(), { s in
27 0
            let result = f(s)
28 0
            return map(set(result.0), { _ in result.1 })
29 0
        })
30
    }
31

32
    /// Modifies the internal state.
33
    ///
34
    /// - Parameter f: Function that modifies the state.
35
    /// - Returns: Unit.
36 1
    static func modify(_ f: @escaping (S) -> S) -> Kind<Self, ()> {
37 1
        return flatMap(get(), { s in set(f(s))})
38
    }
39

40
    /// Retrieves a specific component of the state.
41
    ///
42
    /// - Parameter f: Projection function to obtain part of the state.
43
    /// - Returns: A specific part of the state.
44 1
    static func inspect<A>(_ f: @escaping (S) -> A) -> Kind<Self, A> {
45 1
        return map(get(), f)
46
    }
47
}
48

49
// MARK: Syntax for MonadState
50

51
public extension Kind where F: MonadState {
52
    /// Retrieves the state from the internals of the monad.
53
    ///
54
    /// This is a convenience method to call `MonadState.get` as a static method of this type.
55
    ///
56
    /// - Returns: Maintained state.
57 0
    static func get() -> Kind<F, F.S> {
58 0
        return F.get()
59
    }
60

61
    /// Replaces the state inside the monad.
62
    ///
63
    /// This is a convenience method to call `MonadState.set` as a static method of this type.
64
    ///
65
    /// - Parameter s: New state.
66
    /// - Returns: Unit.
67 0
    static func set(_ s: F.S) -> Kind<F, ()> {
68 0
        return F.set(s)
69
    }
70

71
    /// Embeds a state action into the monad.
72
    ///
73
    /// This is a convenience method to call `MonadState.state` as a static method of this type.
74
    ///
75
    /// - Parameter f: A function that receives the state and computes a value and a new state.
76
    /// - Returns: A value with the output of the function and the new state.
77 0
    static func state(_ f: @escaping (F.S) -> (F.S, A)) -> Kind<F, A> {
78 0
        return F.state(f)
79
    }
80

81
    /// Modifies the internal state.
82
    ///
83
    /// This is a convenience method to call `MonadState.modify` as a static method of this type.
84
    ///
85
    /// - Parameter f: Function that modifies the state.
86
    /// - Returns: Unit.
87 0
    static func modify(_ f: @escaping (F.S) -> F.S) -> Kind<F, ()> {
88 0
        return F.modify(f)
89
    }
90

91
    /// Retrieves a specific component of the state.
92
    ///
93
    /// This is a convenience method to call `MonadState.inspect` as a static method of this type.
94
    ///
95
    /// - Parameter f: Projection function to obtain part of the state.
96
    /// - Returns: A specific part of the state.
97 0
    static func inspect(_ f: @escaping (F.S) -> A) -> Kind<F, A> {
98 0
        return F.inspect(f)
99
    }
100
}

Read our documentation on viewing source code .

Loading