Reputation: 59994
Is there the concept of a Future
that cannot fail in Scala?
I'm transforming a Future[Result]
, which may fail—therefore I handle both a Failure
and a Success
—into a Future[Option[String]]
, carrying an optional error message derived from the failure or success states. So far, so good.
Thing is now, I would like to formally (i.e., with the help of the type system) remember that this future will always hold a Success
and that I won't need to handle the failure case in the future.
Is there a smart way to do this?
Upvotes: 5
Views: 440
Reputation: 40500
You cannot do that "with the help of type system" because there is no way for the type system to guarantee a Future
will not fail, even if you promise that it won't.
Consider this:
Future { doStuff(); }
.recover { case _ => "Failed!" } // Now it always succeeds
.map { _ => Seq.empty[String].head } // Now it does not.
Even if you were going to make any further transformations impossible, once the Future
has been declared to always succeed, that still does not help, because the exception handler (or whatever you do to convert the original future to the "always succeeding one") could throw.
Update: as pointed out in a comment below, the code snippet above is incorrect: the result of .map
is not the same Future
as the result of .recover
. The point stands however. Here is the correct illustration:
Future { doStuff }
.recover { case _ => Seq.empty[String].head }
Upvotes: 6
Reputation: 39577
Isn't this what type-tagging is for?
scala> type Tagged[U] = { type Tag = U }
defined type alias Tagged
scala> type @@[T, U] = T with Tagged[U]
defined type alias $at$at
scala> trait OK ; trait Uncertain
defined trait OK
defined trait Uncertain
scala> type Sure[A] = Future[A] @@ OK
defined type alias Sure
scala> type Unsure[A] = Future[A] @@ Uncertain
defined type alias Unsure
scala> val f = Future.successful(42).asInstanceOf[Sure[Int]]
f: Sure[Int] = Future(Success(42))
then
scala> object X { def p(f: Sure[_]) = "sure" ; def p(f: Unsure[_])(implicit d: DummyImplicit) = "unsure" }
defined object X
scala> X.p(f)
res1: String = sure
It doesn't remain sure under map, of course.
Upvotes: 3