In this blog post, we will discuss about ZIO effect constructors and how we can use them. Then we’ll take a look at Effect constructors for pure computations and side-effecting computations.
Zio Effect Constructors
A functional effect is a template for a concurrent workflow. The template which is mostly descriptive in nature, used to test for any side effects. Such as database interaction, logging, data streaming across the network, or request approval.
We can convert any procedural program into ZIO by wrapping each statement in a constructor such as ZIO.effect and then binding the statements together with flatMap or for comprehensions.
Effect Constructors for Pure Values
Pure values or expressions are expressions without any side-effects. Whereas pure functions are functions whose body consists of pure expressions.
ZIO includes a number of effect constructors for converting pure values into ZIO effects. These constructors are especially useful for merging other ZIO effects built from side-effecting code with pure code.
Thus, ZIO.effect constructor takes side-effecting code, and converts it into a pure value, which merely has any side effects in it. Furthermore, some ZIO characteristics, such as environment, typed errors, and stack safety, can benefit pure code.
The ZIO.succeed effect constructor transforms a value into an effect that succeeds. For example: ZIO.succeed(“Hello, ZIO”) constructs an effect that succeeds with the value Hello, ZIO. The failure type of the effect returned by ZIO.succeed is Nothing, because effects created with this constructor can never fail.
val task1: ZIO[Any, Nothing, String] = ZIO.succeed("Hello, ZIO")
The ZIO.fail constructor transforms a value into an effect that fails with that value. For example: ZIO.fail(new Exception) construct an effect that fails with the specified exception. The success type of the effect returned by ZIO.fail is Nothing, because effects created with this constructor cannot succeed. Also effects which cannot succeed, either because they fail or because they run forever, often use Nothing as the success type.
val task2: ZIO[Any, String, Nothing] = ZIO.fail("This will fail with an exception.")
The ZIO.fromEither effect constructor transforms an Either[E, A] into an IO[E, A] effect. If the Either is a Left, then the resulting ZIO effect will fail with an E, but if it is a Right, then the resulting ZIO effect will succeed with an A.
val task3: ZIO[Any, Nothing, String] = ZIO.fromEither(Right("This is successful"))
Option can be converted into a ZIO effect using ZIO.fromOption . Either an Option[A] is a Some[A] with a value or it is a None, with no other information. So an Option can fail, but there is essentially only one way it could ever fail is with the value None.
val task4: ZIO[Any, Option[Nothing], Int] = ZIO.fromOption(Some(29)) val task5: ZIO[Any, Option[Nothing], Int] = ZIO.fromOption(None)
Try value can be converted into a ZIO effect using ZIO.fromTry . The error type of the resulting effect will always be Throwable, because
Try can only fail with values of type Throwable.
val task6: Task[Int] = ZIO.fromTry(Try(23/0))
Effect Constructors for Side Effects
Effect constructors for side-effecting computations are most important. These constructors translate procedural code into ZIO effects, resulting in blueprints that separate the what from the how.
ZIO can convert both synchronous and asynchronous side-effects into ZIO effects i.e. pure values. These functions can be used to wrap procedural code, allowing us to use all ZIO features in combination with Scala and Java code, as well as third-party libraries. Let’s see some constructors for side effecting computations.
A synchronous side-effect can be converted into a ZIO effect using ZIO.effect . The error type of the resulting effect will always be Throwable, as a side effecting computation can throw an exception which will result in the Throwable type.
val task7: ZIO[Any, Throwable, Unit] = ZIO.effect(println("Learning ZIO !!"))
Sometimes, when we want to convert side-effecting code into a ZIO effect and we know the side-effecting code does not throw any exceptions. For these cases, we can use the constructor ZIO.effectTotal, which converts procedural code into a ZIO effect that cannot fail. For example: Checking the system time or producing a random variable are clearly side effects, but they cannot generate exceptions.
val task8: ZIO[Any, Nothing, Unit] = ZIO.effectTotal(println("This will not throw an exception."))
An asynchronous side-effect with a callback-based API can be converted into a ZIO effect using ZIO.effectAsync. ZIO effects which are asynchronous are much easier to use than callback-based APIs, and they benefit from ZIO features like interruption, resource-safety, and superior error handling.
Thank you guys for making it to the end of the blog I hope you gained some knowledge about different types of ZIO effect constructors. You can also check out other informational blogs here. To know more about Knoldus click here.