@@ -112,7 +112,7 @@ Note that `.e` must be appended to the value the `for` comprehension then
112
112
Regarding the second example of odd behaviour, involving ` if ` , this
113
113
was traced to the fact that the ` filter ` method (of ` LeftProjection `
114
114
and ` RightProjection ` ) returns an ` Option ` instead of an ` Either ` ,
115
- thus allowing ` None ` to be returned when the predicate is ` false ` . A
115
+ thus allowing ` None ` to be returned when the predicate is false. A
116
116
` Left ` (` Right ` ) could not be returned in the case of a
117
117
` RightProjection ` (` LeftProjection ` ) since no value is available to go
118
118
into it.
@@ -130,39 +130,59 @@ pattern-matching in `for` comprehensions involving (projections of)
130
130
Therefore, a third solution has been investigated, whereby ` LeftProj `
131
131
(` RightProj ` ) has a ` withFilter ` method that returns a ` LeftProj `
132
132
(` RightProj ` ) containing a ` Right ` (` Left ` ) if the predicate is
133
- ` false ` , and where the contents of that ` Right ` (` Left ` ) is obtained
133
+ false, and where the contents of that ` Right ` (` Left ` ) is obtained
134
134
using an implicit conversion passed to the ` withFilter ` method in a
135
135
second parameter list:
136
136
137
137
def withFilter[BB >: B](p: A => Boolean)
138
- (implicit aToB: Right.Convert => BB): LeftProj[A, BB] = {
138
+ (implicit aToB: Right.Convert[A] => BB): LeftProj[A, BB] = {
139
139
val e2: Either[A, BB] = e match {
140
140
case Left(a) => if (p(a)) Left(a) else Right(aToB(Right.Convert(a)))
141
141
case Right(b) => Right(b)
142
142
}
143
143
LeftProj(e2)
144
144
}
145
145
146
- Note that ` aToB ` has the type, ` Right.Convert => BB ` , rather than `A =>
147
- BB`, as might have been expected. This deserves the following explanation:
146
+ Note that ` aToB ` has the type, ` Right.Convert[A] => BB ` , rather than
147
+ ` A => BB ` , since we're obliged to wrap the ` a ` in something whose type
148
+ is specific to this type of conversion--from a value in a ` Left ` to
149
+ a value that can go into a ` Right ` --in order that a targeted implicit
150
+ conversion may be supplied. ` Convert ` is a simple case class,
148
151
149
- * ` A => BB ` only permits ` for ` comprehensions that do not feature definitions
150
- * ` Tuple2[...] => BB ` is required if there is 1 definition
151
- * ` Tuple3[...] => BB ` is required if there are 2 definitions, and so on
152
- * the tuple comprises one field for each definition, plus a further one (the first) for ` a `
153
- * ` Any ` is a suitable catch-all, that must be placed in a suitable
154
- container, in order that implicit look-ups should be properly targeted
155
- * ` Right.Convert ` is such a container (for an ` a ` or tuple that is a
156
- 'convert' to the right, and must therefore be converted to a ` BB `
157
- by an implicit conversion)
152
+ case class Convert[+A](a: A)
158
153
159
- This solution therefore requires that an implicit conversion such as
160
- the following be provided whenever the method is used, as is the case
161
- when ` if ` or pattern-matching features in a ` for ` comprehension:
154
+ with a ` Left ` counterpart for use in conversions going the other
155
+ way.
162
156
163
- implicit def f(convert: Right.Convert) = convert.any.toString
157
+ It should be noted that ` a ` is sometimes a tuple:
164
158
165
- Here, ` any ` is an ` a ` or tuple that is a convert to the right, and ` BB ` is ` String ` .
159
+ * in ` for ` comprehensions involving an ` if ` referring to a definition,
160
+ the compiler demands that an implicit conversion from a ` Tuple2[A, X] `
161
+ be provided, where ` X ` is the type of the definition, instead of a
162
+ conversion from an ` A `
163
+
164
+ * if there are two definitions, this will be a ` Tuple3[A, X, Y] ` , where
165
+ ` Y ` is the type of the second definition, and so on
166
+
167
+ * at runtime, if the expression following ` if ` is false, ` withFilter `
168
+ is called as though the type of the ` LeftProj ` were
169
+ ` LeftProj[TupleN[A, ...], BB] ` (instead of ` LeftProj[A, BB] ` ).
170
+
171
+ For example, given the following ` for ` comprehension,
172
+
173
+ val either: Either[String, Int] = Right(1)
174
+ val res = for {
175
+ a <- either.rp
176
+ b = a + 1
177
+ if b > 0
178
+ } yield b
179
+ assert(res.e == Right(2))
180
+
181
+ the compiler would demand a conversion such as the following,
182
+
183
+ implicit def g(convert: Left.Convert[(Int, Int)]) = convert.b.toString
184
+
185
+ so that ` res.e ` would be ` Left("(1,2)") ` if ` b > 0 ` were false.
166
186
167
187
Although this solution has been [ shown] [ project ] to work well,
168
188
it has been objected to on the grounds that [ ` Either ` strictly requires
0 commit comments