Is Scala's Try referentially transparent? - scala

I'm currently working on a presentation about Functional Programming, and came upon the following problem.
Functional Programming intends to separate the 'what' from the 'how', or more precisely, the declaration of a computation from its interpretation. This is why one of the main focus of this paradigm is to represent computations using composable data-structures without making any assumptions about how they are performed. For example:
// Represents a computation that may fail
case class Unsafe[A,B](run: A => B)
// ...
val readIntFromFile: Unsafe[String, Int] = Unsafe { filePath => /* ... */ }
interpret(readIntFromFile)
// Interpreter
def interpret(u: Unsafe[String, Int]): Unit = {
try {
u.run("path/to/file")
} catch {
case e => /* ... */
}
}
This seems to make sense, as side-effects should be only performed during the execution of the computation and not during its declaration. The problem is that in Scala, as it seems, many data-structures break this rule:
object Try {
/** Constructs a `Try` using the by-name parameter. This
* method will ensure any non-fatal exception is caught and a
* `Failure` object is returned.
*/
def apply[T](r: => T): Try[T] =
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
}
Same for Futures:
/** Starts an asynchronous computation and returns a `Future` object with the result of that computation.
*
* The result becomes available once the asynchronous computation is completed.
*
* #tparam T the type of the result
* #param body the asynchronous computation
* #param executor the execution context on which the future is run
* #return the `Future` holding the result of the computation
*/
def apply[T](body: =>T)(implicit #deprecatedName('execctx) executor: ExecutionContext): Future[T] = impl.Future(body)
So, I'm wondering now, are Try and Future really referentially transparent? If not, then how should one handle the error cases without relying on Success and Failure?

Try is referentially transparent as long as you don't use side effects. The purpose of Try is not to control side effects, but to handle a possible exception.
If you need to control side effects in a pure way you can use Task or IO types from libraries like Cats and Scalaz.

Future is definitely not RT, since these two block are not equivalent:
The two futures are executed in parallel:
val fa: Future[Int] = service.call
val fb: Future[Int] = service.call
for { a <- fa; b <- fb } yield a + b
The two futures are executed in sequentially:
for { a <- service.call; b <- service.call } yield a + b
Try is, on the other hand. The proper functional way to handle error is to use Either[ErrorDescription, A] for a method that returns an A but might fail (you could use type ErrorDescription = Throwable for something equivalent to scala.util.Try!).

Related

Cats Effect: Avoid calling unsafeRun on external listener of T => Unit

I am using external API which offers:
def listen(listener: ResponseType => Unit): Handle
My listener returns:
IO[Unit]
Is there a way to inject my listener without a need to call unsafeRun?
listen(msg => myListener(msg).unsafeRunSync())
IO is not only container of your listener. From cats-effect documentation:
A pure abstraction representing the intention to perform a side effect,
where the result of that side effect may be obtained synchronously (via return)
or asynchronously (via callback)
it means IO contains not the some value but intention to perform some side-effect.
Here the most usual ways to work with IO:
Add some effect to the containing of IO using flatMap (this way named composition):
val ioA: IO[A] = ??? // you have some side effect returning A
// here you can have some different side effect returning B: work with DB, read some resource or so on
def aToIOB(a: A): IO[B] = ???
val ioB: IO[B] = ioA.flatMap(aToIOB)
Launching the whole chain of your combinations side effects from 1. using unsafeRunSync or similar functions which run IO. It should be called once in your application and as a rule in the end of the universe (at the end of your program).
// this line launches execution of ioA and aToIOB and will return value of B with side-effects
val b: B = ioB.unsafeRunSync()
So when you see IO[A] you should remember that it is not the similar thing as Option[A] or List[A] and you can just execute IO to get A. You should use combination of IO while your application is not on the end of execution. If so you can run it using unsafeRunSync.
I mean you should build your application without using unsafeRunSync more than one time, and I guess, your signature
def listen(listener: ResponseType => Unit): Handle
should not use IO API, but very similar to Async[F[_]] API, take a look at function async:
/**
* Creates a simple, non-cancelable `F[A]` instance that
* executes an asynchronous process on evaluation.
*
* The given function is being injected with a side-effectful
* callback for signaling the final result of an asynchronous
* process.
*
* This operation could be derived from [[asyncF]], because:
*
* {{{
* F.async(k) <-> F.asyncF(cb => F.delay(k(cb)))
* }}}
*
* As an example of wrapping an impure async API, here's the
* implementation of [[Async.shift]]:
*
* {{{
* def shift[F[_]](ec: ExecutionContext)(implicit F: Async[F]): F[Unit] =
* F.async { cb =>
* // Scheduling an async boundary (logical thread fork)
* ec.execute(new Runnable {
* def run(): Unit = {
* // Signaling successful completion
* cb(Right(()))
* }
* })
* }
* }}}
*
* #see [[asyncF]] for the variant that can suspend side effects
* in the provided registration function.
*
* #param k is a function that should be called with a
* callback for signaling the result once it is ready
*/
def async[A](k: (Either[Throwable, A] => Unit) => Unit): F[A]
Try to concentrate that listen should do in your application and choose correct signature.
Usefull links:
cats-effect IO monad
cats-effect Async typeclass

How the sample Simple IO Type get rid of side effects in "FP in Scala"?

I am reading chapter 13.2.1 and came across the example that can handle IO input and get rid of side effect in the meantime:
object IO extends Monad[IO] {
def unit[A](a: => A): IO[A] = new IO[A] { def run = a }
def flatMap[A,B](fa: IO[A])(f: A => IO[B]) = fa flatMap f
def apply[A](a: => A): IO[A] = unit(a)
}
def ReadLine: IO[String] = IO { readLine }
def PrintLine(msg: String): IO[Unit] = IO { println(msg) }
def converter: IO[Unit] = for {
_ <- PrintLine("Enter a temperature in degrees Fahrenheit: ")
d <- ReadLine.map(_.toDouble)
_ <- PrintLine(fahrenheitToCelsius(d).toString)
} yield ()
I have couple of questions regarding this piece of code:
In the unit function, what does def run = a really do?
In the ReadLine function, what does IO { readLine } really do? Will it really execute the println function or just return an IO type?
What does _ in the for comprehension mean (_ <- PrintLine("Enter a temperature in degrees Fahrenheit: ")) ?
Why it removes the IO side effects? I saw these functions still interact with inputs and outputs.
The definition of your IO is as follows:
trait IO { def run: Unit }
Following that definition, you can understand that writing new IO[A] { def run = a } means initialising an anonymous class from your trait, and assigning a to be the method that runs when you call IO.run. Because a is a by name parameter, nothing is actually ran at creation time.
Any object or class in Scala which follows a contract of an apply method, can be called as: ClassName(args), where the compiler will search for an apply method on the object/class and convert it to a ClassName.apply(args) call. A more elaborate answer can be found here. As such, because the IO companion object posses such a method:
def apply[A](a: => A): IO[A] = unit(a)
The expansion is allowed to happen. Thus we actually call IO.apply(readLine) instead.
_ has many overloaded uses in Scala. This occurrence means "I don't care about the value returned from PrintLine, discard it". It is so because the value returned is of type Unit, which we have nothing to do with.
It is not that the IO datatype removes the part of doing IO, it's that it defers it to a later point in time. We usually say IO runs at the "edges" of the application, in the Main method. These interactions with the out side world will still occur, but since we encapsulate them inside IO, we can reason about them as values in our program, which brings a lot of benefit. For example, we can now compose side effects and depend on the success/failure of their execution. We can mock out these IO effects (using other data types such as Const), and many other surprisingly nice properties.
The simplest way to look at IO monad as a small piece of program definition.
Thus:
This is IO definition, run method defines what IO monad does. new IO[A] { def run = a } is scala way of creating an instance of class and defining method run.
There is a bit of syntactical sugar is going on. IO { readLine } is same as IO.apply { readLine } or IO.apply(readLine) where readLine is call-by-name function of type => String. This calls the unit method from object IO and thus this is just creation of instance of IO class that does not run yet.
Since IO is a monad, for comprehension can be used. It requires storing a result of each monad operation in a syntax like result <- someMonad. To ignore the result, _ can be used, thus _ <- someMonad reads as execute the monad but ignore the result.
This methods are all IO definitions, they don't run anything and thus there is no side effect. Side effects only appears when IO.run is called.

Alternative to await.ready

I have the following code in Scala:
val status: Future[String] = Await.ready(Http(address OK as.String), 1 second)
I'm making a http call and I'm waiting for an answer for a second.
I was told it's not good practice to block using Await.ready.
I'm curious what I can use instead.
Can I use for comprehensions? How?
It generally bad to block on an asynchronous operation, otherwise, why make it asynchronous at all?
You can use various implementations with Future[T], such as registering a continuation to invoke when the result arrives. For example, let's assume you want to parse the String result into a Foo object. You'd get:
val result: Future[Foo] = Http(address OK as.String).map {
s => parseJson[Foo](s)
}
Note that when working with Future[T], you'll end up bubbling them up the call chain of the execution, unless you synchronously block.
Same can be achieved with for comprehension:
for {
s <- Http(address OK as.String)
} yield (parseJson[Foo](s))
Using Await.ready is not a good practice because its blocking. In most of the cases you can compose and transform the futures to achieve the desired result.
But You can use blocking when its absolutely necessary. Here is my answer about blocking and its consequences When to and when not use blocking
Non-Blocking wait
def afterSomeTime(code: => Unit)(duration: FiniteDuration): Unit = {
someActorSystem.scheduler.scheduleOnce(duration) {
code
}
}
Above function will call the code after given duration, you can use any other timer implementation instead of Akka scheduler
case class TimeoutException(msg: String) extends Exception(msg)
def timeout[T](future: => Future[T])(duration: FiniteDuration)(implicit ec: ExecutionContext): Future[T] = {
val promise = Promise[T]()
future.onComplete(promise tryComplete)
afterSomeTime {
promise tryFailure TimeoutException(s"Future timeout after ${duration.toString()}")
}(duration)
promise.future
}

Abstraction for asynchronous computation that cannot fail

Scala Futures are a fine abstraction for asynchronous computation that can fail. What abstraction should I use when I know that there is no failure possible?
Here is a concrete use case:
case class Service123Error(e: Throwable)
val f1: Future[User] =
service123.call()
val f2: Future[Either[Service123Error, User]] =
f1.map(Right.apply)
.recover { case e => Left(Service123Error(e)) }
In this code, the types do not model the fact that f2 always successfully completes. Given several values similar to f2, I know I can Future.sequence over them (i.e. without the fail fast behavior), but the types are not carrying this information.
I would not stick an Either into a Future if it carries the error information. Simply use the failure side of the future.
Future(Right(User)) -> Future[User](User)
Future(Left(Service123Error)) -> Future[User](throw Service123Error)

What are the use cases of scala.concurrent.Promise?

I am reading SIP-14 and the concept of Future makes perfect sense and easy to understand. But have two questions about Promise:
The SIP says Depending on the implementation, it may be the case that p.future == p. How can this be? Are Future and Promise not two different types?
When should we use a Promise? The example producer and consumer code :
import scala.concurrent.{ future, promise }
val p = promise[T]
val f = p.future
val producer = future {
val r = produceSomething()
p success r
continueDoingSomethingUnrelated()
}
val consumer = future {
startDoingSomething()
f onSuccess {
case r => doSomethingWithResult()
}
}
is easy to read but do we really need to write like that? I tried to implement it only with Future and without Promise like this:
val f = future {
produceSomething()
}
val producer = future {
continueDoingSomethingUnrelated()
}
startDoingSomething()
val consumer = future {
f onSuccess {
case r => doSomethingWithResult()
}
}
What is the difference between this and the given example and what makes a Promise necessary?
The Promise and Future are complementary concepts. The Future is a value which will be retrieved, well, sometime in the future and you can do stuff with it when that event happens. It is, therefore, the read or out endpoint of a computation - it is something that you retrieve a value from.
A Promise is, by analogy, the writing side of the computation. You create a promise which is the place where you'll put the result of the computation and from that promise you get a future that will be used to read the result that was put into the promise. When you'll complete a Promise, either by failure or success, you will trigger all the behavior which was attached to the associated Future.
Regarding your first question, how can it be that for a promise p we have p.future == p. You can imagine this like a single-item buffer - a container which is initially empty and you can afterwords store one value which will become its content forever. Now, depending on your point of view this is both a Promise and a Future. It is promise for someone who intends to write the value in the buffer. It is a future for someone who waits for that value to be put in the buffer.
Specifically, for the Scala concurrent API, if you take a look at the Promise trait in here you can see how the methods from the Promise companion object are implemented :
object Promise {
/** Creates a promise object which can be completed with a value.
*
* #tparam T the type of the value in the promise
* #return the newly created `Promise` object
*/
def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]()
/** Creates an already completed Promise with the specified exception.
*
* #tparam T the type of the value in the promise
* #return the newly created `Promise` object
*/
def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))
/** Creates an already completed Promise with the specified result.
*
* #tparam T the type of the value in the promise
* #return the newly created `Promise` object
*/
def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))
}
Now, those implementation of promises, DefaultPromise and KeptPromise can be found here. They both extend a base little trait which happens to have the same name, but it is located in a different package:
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
}
So you can see what they mean by p.future == p.
DefaultPromise is the buffer I was referring above, while KeptPromise is a buffer with the value put in from its very creation.
Regarding your example, the future block you use there actually creates a promise behind the scenes. Let's look at the definition of future in here :
def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body)
By following the chain of methods you end up in the impl.Future:
private[concurrent] object Future {
class PromiseCompletingRunnable[T](body: => T) extends Runnable {
val promise = new Promise.DefaultPromise[T]()
override def run() = {
promise complete {
try Success(body) catch { case NonFatal(e) => Failure(e) }
}
}
}
def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] = {
val runnable = new PromiseCompletingRunnable(body)
executor.execute(runnable)
runnable.promise.future
}
}
So, as you can see, the result you get from your producer block gets poured into a promise.
LATER EDIT:
Regarding the real-world use: Most of the time you won't deal with promises directly. If you'll use a library which performs asynchronous computation then you'll just work with the futures returned by the library's methods. Promises are, in this case, created by the library - you're just working with the reading end of what those methods do.
But if you need to implement your own asynchronous API you'll have to start working with them.
Suppose you need to implement an async HTTP client on top of, lets say, Netty. Then your code will look somewhat like this
def makeHTTPCall(request: Request): Future[Response] = {
val p = Promise[Response]
registerOnCompleteCallback(buffer => {
val response = makeResponse(buffer)
p success response
})
p.future
}