Blog Infos
Author
Published
Topics
Published
Topics

 

Exploring Eval Monad

 

In simple terms, a monad is a design pattern in functional programming that allows you to write code that can handle computation in a more composable and predictable way. It’s like a toolbox that helps you build complex programs by breaking them down into smaller, easier-to-manage parts. To know more about monad checkout our previous post to know it in depth.

What is the Eval Monad❓

Arrow KT’s Eval monad is a powerful tool for controlling the timing and execution of code in a Kotlin program. It’s designed to handle tasks that are either:

  • Heavy computations that you want to defer until they’re actually needed
  • Tasks that you want to run only once, even if you call them multiple times

By using the Eval monad, you can ensure that your code runs efficiently, without doing any unnecessary work.

Why use the Eval Monad ❓

There are several reasons, why you might want to use the Eval Monad in your Kotlin applications. Some of the most common use cases include:

  • Performance optimization: By delaying the evaluation of computation until it is needed, you can improve the performance of your application.
  • Lazy evaluation: If you only need the result of a computation under certain conditions, you can use the Eval Monad to ensure that the computation is only performed when necessary.
  • Memoization: If you have a computation that is expensive to perform, you can use the Eval Monad to cache the result and avoid having to recompute it every time it is needed.

To use Eval monad you need to implement Arrow Kt in your project, you can add the following dependency to your build.gradle file:

dependencies {
    implementation "io.arrow-kt:arrow-core:$arrow_version"
}

For detailed information on how to implement Arrow.Kt in your project and latest version be sure to check out the Arrow.Kt website and documentation.

Exploring Eval Monad 🌐

There are three different types of Eval monad: nowlater, and always. Let’s take a closer look at each one:

  • Now: Computes the value immediately.
  • Later: Defers computation until it is actually needed.
  • Always: Recomputes the value each time it is needed.

Let’s understand each of these in detail with examples:

Exploring Eval Monad

Now 💥

The now type of Eval monad runs its computation immediately, when it’s called. This is the equivalent of just calling a function normally in Kotlin.

For example, if you want to calculate the result of a mathematical expression and store it in a variable, you could use the now type of Eval monad like this:

val result = Eval.now(1 + 2 ).value() 
println(result) // 3

In this case, the expression 1 + 2 is calculated immediately, and its result is stored in the result variable.

Let’s check with an real example 🚁

💡 Have you ever wanted to calculate something and get the result right away? That’s where now comes in! The now method evaluates the lazy computation immediately, just like a regular function.

Let’s say, you want to get the current temperature in your city. You can use the now method to fetch the temperature right away and not wait for any other computations to be done.

Here’s a code example in Kotlin:

val temperature = Eval.now(25)
println("The temperature is: ${temperature.value()}")

Output:

The temperature is: 25
Later 💭

The later type of Eval monad defers its computation until its result is actually needed. This means that the computation is only executed once, when its result is called, even if the later instance is used multiple times.

Here’s an example of how you could use the later type of Eval monad to cache the result of a heavy computation:

val computation = Eval.later { 
    println("Running the computation...") 
    1 + 2 
} 

println("First call") 
println(computation.value()) // Running the computation... 3 

println("Second call") 
println(computation.value()) // 3

In this example, you can see that the message “Running the computation…” is only printed once, even though we’re calling the computation instance multiple times. This is because the computation is only executed once, and its result is cached for subsequent calls.

Here’s a real-life example of the later monad in action 💡

Let’s say you’re making a food delivery app and you want to calculate the total cost of a customer’s order. But, you also want to include a $5 delivery fee.

So, you have two values to calculate: the cost of the food and the delivery fee.

Normally, you would add these two values together to get the final cost. But with the later monad, you can delay the calculation of the delivery fee until the food cost is known.

Here’s how you could use the later monad to implement this in code:

val foodCost = Eval.later { /* calculate the cost of the food */ }
val deliveryFee = Eval.later { 5 }

val totalCost = foodCost.map { cost -> cost + deliveryFee.value() }

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

Jobs

With this implementation, the delivery fee is only calculated when deliveryFee.value() is called, which happens when totalCost is evaluated.

This is a great example of how the later monad can be used to defer calculations until the values they depend on are known. 🤓

Always 👨‍💻

Always is one of the three types of Eval monads in the Arrow Kotlin library. As the name suggests, always evaluates to a constant value, no matter when you run it.

Think of it like this: you have a function that takes a string input, and you want to always return a message that says “Hello, $input”. You could write that function like this:

fun sayHello(name: String): Eval<String> = Eval.always { "Hello, $name" }

And every time you run this sayHello function, you’ll get the same result:

val greeting = sayHello("John").value()
println(greeting) // prints "Hello, John"
Let’s take real use case of always :

Suppose you have an app that allows users to search for a product, and you have a database of products. The database takes time to fetch the data, and it’s important that you only fetch the data once.

You can use the always function in this case to ensure that the database is only queried once, and the results are cached for future use. Here’s how the code would look like:

val fetchProducts: Eval<List<Product>> = Eval.always {
  println("Querying the database...")
  listOf(Product("product1"), Product("product2"), Product("product3"))
}

val firstCall = fetchProducts.value()
println("Result of first call: $firstCall")

val secondCall = fetchProducts.value()
println("Result of second call: $secondCall")

In this example, the fetchProducts is an Eval instance that represents the calculation of fetching the products from the database. The always function is used to create the instance, and the function passed to always will only be executed once.

When we call fetchProducts.value() for the first time, it will print “Querying the database…” as it is executing the calculation. But when we call it for the second time, it won’t execute the calculation again, it will just return the cached result from the first call, as the always function ensures that the calculation is executed only once.

So, in this example, the always function is used to cache the result of an expensive computation and ensure that it is only executed once.

💡 Keep in mind, that always is ideal for caching the result of a calculation that is guaranteed to always be the same and is too expensive to perform multiple times.

In Conclusion 👐

The Eval monad is a powerful tool in the Arrow library that provides a way to defer computations and keep track of actions performed. With its three types nowlater, and always, you can choose the best type for your use case based on your requirements.

In this article, we explored the concept of the Eval monad and its different types with real-life examples. I hope this article helped you understand the Eval monad

Let’s give this article a round of applause 🎉 and don’t forget to follow for more amazing content!

This article was originally published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu