Exercises
-
Implement a ZIO version of the function
readFileby using theZIO.attemptconstructor.def readFile(file: String): String = {val source = scala.io.Source.fromFile(file)try source.getLines().mkStringfinally source.close()}def readFileZio(file: String) = ???
2. Implement a ZIO version of the function `writeFile` by using the `ZIO.attempt` constructor.
```scala def writeFile(file: String, text: String): Unit = { import java.io._ val pw = new PrintWriter(new File(file)) try pw.write(text) finally pw.close }
def writeFileZio(file: String, text: String) = ???-
Using the
flatMapmethod of ZIO effects, together with thereadFileZioandwriteFileZiofunctions that you wrote, implement a ZIO version of the functioncopyFile.def copyFile(source: String, dest: String): Unit = {val contents = readFile(source)writeFile(dest, contents)}def copyFileZio(source: String, dest: String) = ???
4. Rewrite the following ZIO code that uses `flatMap` into a _for comprehension_.
```scala def printLine(line: String) = ZIO.attempt(println(line)) val readLine = ZIO.attempt(scala.io.StdIn.readLine())
printLine("What is your name?").flatMap(_ => readLine.flatMap(name => printLine(s"Hello, $name!")) )-
Rewrite the following ZIO code that uses
flatMapinto a for comprehension.val random = ZIO.attempt(scala.util.Random.nextInt(3) + 1)def printLine(line: String) = ZIO.attempt(println(line))val readLine = ZIO.attempt(scala.io.StdIn.readLine())random.flatMap { int =>printLine("Guess a number from 1 to 3:").flatMap { _ =>readLine.flatMap { num =>if (num == int.toString) printLine("You guessed right!")else printLine(s"You guessed wrong, the number was $int!")}}}
6. Implement the `zipWith` function in terms of the toy model of a ZIO effect. The function should return an effect that sequentially composes the specified effects, merging their results with the specified user-defined function.
```scala final case class ZIO[-R, +E, +A](run: R => Either[E, A])
def zipWith[R, E, A, B, C]( self: ZIO[R, E, A], that: ZIO[R, E, B] )(f: (A, B) => C): ZIO[R, E, C] = ???-
Implement the
collectAllfunction in terms of the toy model of a ZIO effect. The function should return an effect that sequentially collects the results of the specified collection of effects.final case class ZIO[-R, +E, +A](run: R => Either[E, A])def collectAll[R, E, A](in: Iterable[ZIO[R, E, A]]): ZIO[R, E, List[A]] =???
8. Implement the `foreach` function in terms of the toy model of a ZIO effect. The function should return an effect that sequentially runs the specified function on every element of the specified collection.
```scala final case class ZIO[-R, +E, +A](run: R => Either[E, A])
def foreach[R, E, A, B]( in: Iterable[A] )(f: A => ZIO[R, E, B]): ZIO[R, E, List[B]] = ???-
Implement the
orElsefunction in terms of the toy model of a ZIO effect. The function should return an effect that tries the left-hand side, but if that effect fails, it will fall back to the effect on the right-hand side.final case class ZIO[-R, +E, +A](run: R => Either[E, A])def orElse[R, E1, E2, A](self: ZIO[R, E1, A],that: ZIO[R, E2, A]): ZIO[R, E2, A] =???
10. Using the following code as a foundation, write a ZIO application that prints out the contents of whatever files are passed into the program as command-line arguments. You should use the function `readFileZio` that you developed in these exercises, as well as `ZIO.foreach`.
```scala object Cat extends ZIOAppDefault { def run = for { args <- getArgs // _ <- ??? } yield () }-
Using
ZIO.failandZIO.succeed, implement the following function, which converts anEitherinto a ZIO effect:def eitherToZIO[E, A](either: Either[E, A]): ZIO[Any, E, A] = ???
12. Using `ZIO.fail` and `ZIO.succeed`, implement the following function, which converts a `List` into a ZIO effect by looking at the head element in the list and ignoring the rest of the elements.
```scala def listToZIO[A](list: List[A]): ZIO[Any, None.type, A] = ??? ```
13. Using `ZIO.succeed`, convert the following procedural function into a ZIO function:
```scala def currentTime(): Long = java.lang.System.currentTimeMillis()
lazy val currentTimeZIO: ZIO[Any, Nothing, Long] = ???-
Using
ZIO.async, convert the following asynchronous, callback-based function into a ZIO function:def getCacheValue(key: String,onSuccess: String => Unit,onFailure: Throwable => Unit): Unit =???def getCacheValueZio(key: String): ZIO[Any, Throwable, String] =???
15. Using `ZIO.async`, convert the following asynchronous, callback-based function into a ZIO function:
```scala trait User
def saveUserRecord( user: User, onSuccess: () => Unit, onFailure: Throwable => Unit ): Unit = ???
def saveUserRecordZio(user: User): ZIO[Any, Throwable, Unit] = ???-
Using
ZIO.fromFuture, convert the following code to ZIO:import scala.concurrent.{ExecutionContext, Future}trait Querytrait Resultdef doQuery(query: Query)(implicitec: ExecutionContext): Future[Result] =???def doQueryZio(query: Query): ZIO[Any, Throwable, Result] =???
17. Using the `Console`, write a little program that asks the user what their name is and then prints it out to them with a greeting.
``` object HelloHuman extends ZIOAppDefault { val run = ??? } ```
18. Using the `Console` and `Random` services in ZIO, write a little program that asks the user to guess a randomly chosen number between 1 and 3 and prints out if they are correct or not.
```scala import zio._
object NumberGuessing extends ZIOAppDefault { val run = ??? }-
Using the
Consoleservice and recursion, write a function that will repeatedly read input from the console until the specified user-defined function evaluates totrueon the input.import java.io.IOExceptiondef readUntil(acceptInput: String => Boolean): ZIO[Any, IOException, String] =???
20. Using recursion, write a function that will continue evaluating the specified effect until the specified user-defined function evaluates to `true` on the output of the effect.
```scala def doWhile[R, E, A]( body: ZIO[R, E, A] )(condition: A => Boolean): ZIO[R, E, A] = ???