Jean-Philippe Pellet
Jean-Philippe Pellet

Reputation: 59994

Future that cannot fail in Scala

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

Answers (2)

Dima
Dima

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

som-snytt
som-snytt

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

Related Questions