-
Notifications
You must be signed in to change notification settings - Fork 118
/
Copy pathOperators.swift
135 lines (124 loc) · 4.6 KB
/
Operators.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
prefix operator /
/// Returns a case path for the given embed function.
///
/// - Note: This operator is only intended to be used with enum cases that have no associated
/// values. Its behavior is otherwise undefined.
/// - Parameter embed: An embed function.
/// - Returns: A case path.
public prefix func / <Root, Value>(
embed: @escaping (Value) -> Root
) -> CasePath<Root, Value> {
.case(embed)
}
/// Returns a void case path for a case with no associated value.
///
/// - Note: This operator is only intended to be used with enum cases that have no associated
/// values. Its behavior is otherwise undefined.
/// - Parameter root: A case with no an associated value.
/// - Returns: A void case path.
public prefix func / <Root>(
root: Root
) -> CasePath<Root, Void> {
.case(root)
}
/// Returns the identity case path for the given type. Enables `/MyType.self` syntax.
///
/// - Parameter type: A type for which to return the identity case path.
/// - Returns: An identity case path.
public prefix func / <Root>(
type: Root.Type
) -> CasePath<Root, Root> {
.self
}
/// Identifies and returns a given case path. Enables shorthand syntax on static case paths, _e.g._
/// `/.self` instead of `.self`.
///
/// - Parameter type: A type for which to return the identity case path.
/// - Returns: An identity case path.
public prefix func / <Root>(
type: CasePath<Root, Root>
) -> CasePath<Root, Root> {
.self
}
/// Returns a function that can attempt to extract associated values from the given enum case
/// initializer.
///
/// Use this operator to create new transform functions to pass to higher-order methods like
/// `compactMap`:
///
/// [Result<Int, Error>.success(42), .failure(MyError()]
/// .compactMap(/Result.success)
/// // [42]
///
/// - Note: This operator is only intended to be used with enum case initializers. Its behavior is
/// otherwise undefined.
/// - Parameter case: An enum case initializer.
/// - Returns: A function that can attempt to extract associated values from an enum.
public prefix func / <Root, Value>(
case: @escaping (Value) -> Root
) -> (Root) -> Value? {
extract(`case`)
}
/// Returns a void case path for a case with no associated value.
///
/// - Note: This operator is only intended to be used with enum cases that have no associated
/// values. Its behavior is otherwise undefined.
/// - Parameter root: A case with no an associated value.
/// - Returns: A void case path.
public prefix func / <Root>(
root: Root
) -> (Root) -> Void? {
(/root).extract
}
precedencegroup CasePathCompositionPrecedence {
associativity: right
}
infix operator ..: CasePathCompositionPrecedence
extension CasePath {
/// Returns a new case path created by appending the given case path to this one.
///
/// The operator version of `CasePath.appending(path:)`. Use this method to extend this case path
/// to the value type of another case path.
///
/// - Parameters:
/// - lhs: A case path from a root to a value.
/// - rhs: A case path from the first case path's value to some other appended value.
/// - Returns: A new case path from the first case path's root to the second case path's value.
public static func .. <AppendedValue>(
lhs: CasePath,
rhs: CasePath<Value, AppendedValue>
) -> CasePath<Root, AppendedValue> {
return lhs.appending(path: rhs)
}
/// Returns a new case path created by appending the given embed function.
///
/// - Parameters:
/// - lhs: A case path from a root to a value.
/// - rhs: An embed function from an appended value.
/// - Returns: A new case path from the first case path's root to the second embed function's value.
public static func .. <AppendedValue>(
lhs: CasePath,
rhs: @escaping (AppendedValue) -> Value
) -> CasePath<Root, AppendedValue> {
lhs.appending(path: .case(rhs))
}
}
/// Returns a new extract function by appending the given extract function with an embed function.
///
/// Useful when composing extract functions together.
///
/// [Result<Int?, Error>.success(.some(42)), .success(nil), .failure(MyError())]
/// .compactMap(/Result.success..Optional.some)
/// // [42]
///
/// - Parameters:
/// - lhs: An extract function from a root to a value.
/// - rhs: An embed function from some other appended value to the extract function's value.
/// - Returns: A new extract function from the first extract function's root to the second embed
/// function's appended value.
public func .. <Root, Value, AppendedValue>(
lhs: @escaping (Root) -> Value?,
rhs: @escaping (AppendedValue) -> Value
) -> (Root) -> AppendedValue? {
return { root in lhs(root).flatMap(extract(rhs)) }
}