1
import Foundation
2

3
/// A Functor provides a type with the ability to transform its value type into another type, while preserving its structure.
4
///
5
/// Using the encoding for HKTs in Bow, in the type `Kind<F, A>`, `A` is the value type and `F` represents the structure of the type. An instance of `Functor` for `F` allows to transform `A` into another type, while maintaining `F` unchanged.
6
public protocol Functor: Invariant {
7
    /// Creates a new value transforming the type using the provided function, preserving the structure of the original type.
8
    ///
9
    /// The implementation of this function must obey two laws:
10
    ///
11
    /// 1. Preserve identity:
12
    ///
13
    ///         map(fa, id) == fa
14
    ///
15
    /// 2. Preserve composition:
16
    ///
17
    ///         map(map(fa, f), g) == map(fa, compose(g, f))
18
    ///
19
    /// - Parameters:
20
    ///   - fa: A value in the context of the type implementing this instance of `Functor`.
21
    ///   - f: A transforming function.
22
    /// - Returns: The result of transforming the value type using the provided function, maintaining the structure of the original value.
23
    static func map<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B) -> Kind<Self, B>
24
}
25

26
// MARK: Related functions
27
public extension Functor {
28
    // Docs inherited from `Invariant`
29 1
    static func imap<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B, _ g: @escaping (B) -> A) -> Kind<Self, B> {
30 1
        return map(fa, f)
31
    }
32
    
33
    /// Creates a new value transforming the type using the provided key path, preserving the structure of the original type.
34
    ///
35
    /// - Parameters:
36
    ///   - fa: A value in the context of the type implementing this instance of `Functor`.
37
    ///   - keyPath: A key path.
38
    /// - Returns: The result of transforming the value type using the provided function, maintaining the structure of the original value.
39 0
    static func map<A, B>(_ fa: Kind<Self, A>, _ keyPath: KeyPath<A, B>) -> Kind<Self, B> {
40 0
        return map(fa, { a in a[keyPath: keyPath] })
41
    }
42

43
    /// Given a function, provides a new function lifted to the context type implementing this instance of `Functor`.
44
    ///
45
    /// - Parameter f: Function to be lifted.
46
    /// - Returns: Function in the context implementing this instance of `Functor`.
47 1
    static func lift<A, B>(_ f: @escaping (A) -> B) -> (Kind<Self, A>) -> Kind<Self, B> {
48 1
        return { fa in map(fa, f) }
49
    }
50

51
    /// Replaces the value type by the `Void` type.
52
    ///
53
    /// - Parameter fa: Value to be transformed.
54
    /// - Returns: New value in the context implementing this instance of `Functor`, with `Void` as value type.
55 1
    static func void<A>(_ fa: Kind<Self, A>) -> Kind<Self, ()> {
56 1
        return map(fa, {_ in })
57
    }
58

59
    /// Transforms the value type and pairs it with its original value.
60
    ///
61
    /// - Parameters:
62
    ///   - fa: Value to be transformed.
63
    ///   - f: Transforming function.
64
    /// - Returns: A pair with the original value and its transformation, in the context of the original value.
65 1
    static func fproduct<A, B>(_ fa: Kind<Self, A>, _ f: @escaping (A) -> B) -> Kind<Self, (A, B)> {
66 1
        return map(fa, { a in (a, f(a)) })
67
    }
68

69
    /// Transforms the value type with a constant value.
70
    ///
71
    /// - Parameters:
72
    ///   - fa: Value to be transformed.
73
    ///   - b: Constant value to replace the value type.
74
    /// - Returns: A new value with the structure of the original value, with its value type transformed.
75 1
    static func `as`<A, B>(_ fa: Kind<Self, A>, _ b: B) -> Kind<Self, B> {
76 1
        return map(fa, { _ in b })
77
    }
78

79
    /// Transforms the value type by making a tuple with a new constant value to the left of the original value type.
80
    ///
81
    /// - Parameters:
82
    ///   - fa: Value to be transformed.
83
    ///   - b: Constant value for the tuple.
84
    /// - Returns: A new value with the structure of the original value, with a tuple in its value type.
85 1
    static func tupleLeft<A, B>(_ fa: Kind<Self, A>, _ b: B) -> Kind<Self, (B, A)> {
86 1
        return map(fa, { a in (b, a) })
87
    }
88

89
    /// Transforms the value type by making a tuple with a new constant value to the right of the original value type.
90
    ///
91
    /// - Parameters:
92
    ///   - fa: Value to be transformed.
93
    ///   - b: Constant value for the tuple.
94
    /// - Returns: A new value with the structure of the original value, with a tuple in its value type.
95 1
    static func tupleRight<A, B>(_ fa: Kind<Self, A>, _ b: B) -> Kind<Self, (A, B)> {
96 1
        return map(fa, { a in (a, b) })
97
    }
98
}
99

100
// MARK: Syntax for Functor
101

102
public extension Kind where F: Functor {
103
    /// Creates a new value transforming the type using the provided function, preserving the structure of the original type.
104
    ///
105
    /// This is a convenience method to call `Functor.map` as an instance method in this type.
106
    ///
107
    /// - Parameters:
108
    ///   - f: A transforming function.
109
    /// - Returns: The result of transforming the value type using the provided function, maintaining the structure of the original value.
110 1
    func map<B>(_ f: @escaping (A) -> B) -> Kind<F, B> {
111 1
        return F.map(self, f)
112
    }
113
    
114
    /// Creates a new value transforming the type using the provided key path, preserving the structure of the original type.
115
    ///
116
    /// This is a convenience method to call `Functor.map` as an instance method in this type.
117
    ///
118
    /// - Parameters:
119
    ///   - keyPath: A key path.
120
    /// - Returns: The result of transforming the value type using the provided function, maintaining the structure of the original value.
121 0
    func map<B>(_ keyPath: KeyPath<A, B>) -> Kind<F, B> {
122 0
        return F.map(self, keyPath)
123
    }
124

125
    /// Given a function, provides a new function lifted to the context type implementing this instance of `Functor`.
126
    ///
127
    /// This is a convenience method to call `Functor.lift` as a static method in this type.
128
    ///
129
    /// - Parameter f: Function to be lifted.
130
    /// - Returns: Function in the context implementing this instance of `Functor`.
131 0
    static func lift<A, B>(_ f: @escaping (A) -> B) -> (Kind<F, A>) -> Kind<F, B> {
132 0
        return { fa in fa.map(f) }
133
    }
134

135
    /// Replaces the value type by the `Void` type.
136
    ///
137
    /// This is a convenience method to call `Functor.void` as an instance method of this type.
138
    ///
139
    /// - Returns: New value in the context implementing this instance of `Functor`, with `Void` as value type.
140 0
    func void() -> Kind<F, ()> {
141 0
        return F.void(self)
142
    }
143

144
    /// Transforms the value type and pairs it with its original value.
145
    ///
146
    /// This is a conveninence method to call `Functor.fproduct` as an instance method of is type.
147
    ///
148
    /// - Parameters:
149
    ///   - f: Transforming function.
150
    /// - Returns: A pair with the original value and its transformation, in the context of the original value.
151 0
    func fproduct<B>(_ f: @escaping (A) -> B) -> Kind<F, (A, B)> {
152 0
        return F.fproduct(self, f)
153
    }
154

155
    /// Transforms the value type with a constant value.
156
    ///
157
    /// This is a convenience method to call `Functor.as` as an instance method of this type.
158
    ///
159
    /// - Parameters:
160
    ///   - b: Constant value to replace the value type.
161
    /// - Returns: A new value with the structure of the original value, with its value type transformed.
162 0
    func `as`<B>(_ b: B) -> Kind<F, B> {
163 0
        return F.as(self, b)
164
    }
165

166
    /// Transforms the value type by making a tuple with a new constant value to the left of the original value type.
167
    ///
168
    /// This is a conveninence method to call `Functor.tupleLeft` as an instance method of this type.
169
    ///
170
    /// - Parameters:
171
    ///   - b: Constant value for the tuple.
172
    /// - Returns: A new value with the structure of the original value, with a tuple in its value type.
173 0
    func tupleLeft<B>(_ b: B) -> Kind<F, (B, A)> {
174 0
        return F.tupleLeft(self, b)
175
    }
176

177
    /// Transforms the value type by making a tuple with a new constant value to the right of the original value type.
178
    ///
179
    /// This is a convenience method to call `Functor.tupleRight` as an instance method of this type.
180
    ///
181
    /// - Parameters:
182
    ///   - b: Constant value for the tuple.
183
    /// - Returns: A new value with the structure of the original value, with a tuple in its value type.
184 0
    func tupleRight<B>(_ b: B) -> Kind<F, (A, B)> {
185 0
        return F.tupleRight(self, b)
186
    }
187
}

Read our documentation on viewing source code .

Loading