On 8/25/16 10:22 PM, Holger wrote:
However, when I use the for comprehension to
combine a
Maybe and
a
Future which holds
another
Maybe the
Scala compiler gives me the error message
missing parameter type at the line of
the outer generator:
def
retrieveStreet(id: String): Future[Maybe[String, String]] = ...
val outerMaybe: Maybe[String, String] = ...
val result = for {
id ←
outerMaybe // error message
"missing parameter type" here!
street ←
retrieveStreet(id)
} yield
street
But when instead of using
for I call the
flatMap and
map methods explicitly, it works:
val result2 =
outerMaybe.flatMap(
id =>
retrieveStreet(id) )
.map(
street =>
street )
This is not the expansion of
result. Here it is:
val result3 =
outerMaybe.flatMap( id =>
retrieveStreet(id).map(street => street) )
Which gives
[error] ....scala:37: missing parameter type
[error] outerMaybe.flatMap( id =>
[error] ^
(I also get this error message when I try to combine a
Maybe with
another Maybe
in a for comprehension.)
So the questions are:
- Shouldn't these two
alternatives behave exactly the same? Why does the
compiler figure out the correct flatMap method to call,
when calling flatMap
explicitly?
It doesn't in either case, because there's no notion of similarity
between overloads. As soon as you have multiple overloads, you lose
the benefit of the "expected type" for the argument, which gives you
the lambda argument type, and this is required for both forms.
Expressions of the form x => f(x) where f is
a method are treated specially; you get the benefit of the whole
type of the f method. It is like you wrote outerMaybe.flatMap(retrieveStreet).
The expansion you gave for result2 fits this pattern, and
therefore does not require an "expected type" for the lambda
argument in order to work. But the true expansion of the for-comprehension,
result3 above, does not fit this pattern.
- Since apparently the
compiler is confused by the two flatMap implementations, is
there a way to tell it (by a type specification
anywhere) which one should be called in the for
comprehension
The problem is overloading, so get rid of overloading. If you wish
to provide these two variants of
flatMap, provide a
typeclass and two instances, one for
Future and one for
Maybe.
The signature for the
only flatMap method would
look something like
def flatMap[W, Z](f: V => W)(implicit ev: Maybe.FlatMap[E, V, W, Z]): Z
and instances for
FlatMap[E, V, Maybe[F, W], Maybe[F, W]]
and
FlatMap[E, V, Future[W], Future[Maybe[E, W]]] in
Maybe.FlatMap's
companion.
Greetings,
Stephen.