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`, `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(_ fa: Kind, _ f: @escaping (A) -> B) -> Kind ``` 24 ```} ``` 25 26 ```// MARK: Related functions ``` 27 ```public extension Functor { ``` 28 ``` // Docs inherited from `Invariant` ``` 29 1 ``` static func imap(_ fa: Kind, _ f: @escaping (A) -> B, _ g: @escaping (B) -> A) -> Kind { ``` 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(_ fa: Kind, _ keyPath: KeyPath) -> Kind { ``` 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(_ f: @escaping (A) -> B) -> (Kind) -> Kind { ``` 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(_ fa: Kind) -> Kind { ``` 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(_ fa: Kind, _ f: @escaping (A) -> B) -> Kind { ``` 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`(_ fa: Kind, _ b: B) -> Kind { ``` 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(_ fa: Kind, _ b: B) -> Kind { ``` 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(_ fa: Kind, _ b: B) -> Kind { ``` 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(_ f: @escaping (A) -> B) -> Kind { ``` 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(_ keyPath: KeyPath) -> Kind { ``` 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(_ f: @escaping (A) -> B) -> (Kind) -> Kind { ``` 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 { ``` 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(_ f: @escaping (A) -> B) -> Kind { ``` 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) -> Kind { ``` 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) -> Kind { ``` 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) -> Kind { ``` 185 0 ``` return F.tupleRight(self, b) ``` 186 ``` } ``` 187 ```} ```

Read our documentation on viewing source code .