How to chain functions returning Validated, Option, Either? (Monad Transformer) - kotlin

I have simple three functions returning arrow-kt data types
fun validate(input): Validated<Error, Input> = ...
fun fetch(input): Option<Error, InputEntity> = ...
fun performAction(inputEntity): Either<Error, Output> = ...
And want to chain something like this (can use any available function instead of map)
validate(input)
.map{fetch(it)}
.map{performAction(it)}
Only solution I could come up with is to replace Validated and Option with Either and chain using flatMap. Is there any better functional way to make it work without updating the existing functions?

👋 What #pablisco described is correct, but you can keep it simpler by using some syntax extensions we provide to convert from one type to the other. Note that both options are correct, but Monad Transformers can be a bit convoluted and too powerful, and they're also prone to get removed from Arrow soon, once we finally figure out our delimited continuations style completely. But that is out of scope here. Here is how you could solve it by using the extensions I mentioned:
import arrow.core.*
import arrow.core.extensions.fx
sealed class Error {
object Error1 : Error()
object Error2 : Error()
}
data class InputEntity(val input: String)
data class Output(val input: InputEntity)
fun validate(input: String): Validated<Error, InputEntity> = InputEntity(input).valid()
fun fetch(input: String): Option<InputEntity> = InputEntity(input).some()
fun performAction(inputModel: InputEntity): Either<Error, Output> = Output(inputModel).right()
fun main() {
val input = "Some input"
Either.fx<Error, Output> {
val validatedInput = !validate(input).toEither()
val fetched = !fetch(validatedInput.input).toEither { Error.Error1 /* map errors here */ }
!performAction(fetched)
}
}
Hope it was useful 👍

What you are looking for is called a Monad Transformer. In Arrow, you may have seen them already, they end with a T at the end. Like OptionT or EitherT.
There are some good examples here for EitherT:
https://arrow-kt.io/docs/0.10/arrow/mtl/eithert/
And here for OptionT:
https://arrow-kt.io/docs/0.10/arrow/mtl/optiont/
The idea would be that to choose what your final value is going to be (let's say Either) and using an FX block you can then use EitherT to convert the other types to an Either.

Related

How to slice vararg argument

I wrote an extension function to get an element of an JSON object by its name:
fun JSONObject.obj (name: String): JSONObject? =
try { this.getJSONObject(name) }
catch (e: JSONException) { null }
Now I want to extend this for nested JSON objects. I wrote the following:
tailrec fun JSONObject.obj (first: String, vararg rest: String): JSONObject? =
if (rest.size == 0)
obj(first)
else
obj(first)?.obj(rest[0], *rest.drop(1).toTypedArray())
But this looks quite inefficient to me.
What is the best way to slice a vararg argument?
We could use vararg only in the public function, but then internally use list for recursion:
fun JSONObject.obj (first: String, vararg rest: String): JSONObject? = obj(first, rest.asList())
private tailrec fun JSONObject.obj (first: String, rest: List<String>): JSONObject? =
if (rest.size == 0)
obj(first)
else
obj(first)?.obj(rest[0], rest.subList(1, rest.size))
Both asList() and subList() don't copy data, but only wrap the existing collection. Still, this is far from ideal, because it creates a new object for each iteration and it may create a chain of views (it depends on internal implementation of subList()). Alternatively, the internal function could receive an array and offset - this will solve both above problems.
Generally, I suggest to not try turning Kotlin into something it is not. It has limited support for functional constructs, but it is not a functional language. Without the linked list implementation which could be easily split into head and tail, this style of code will be always inefficient and/or cumbersome. You can look for such implementation, for example in Arrow or kotlinx.collections.immutable. The latter has ImmutableList with optimized subList() - you can use it with the solution provided above to avoid creating a chain of lists.
Update
As a matter of fact, basic lists implementations in the Java stdlib also provide optimized subList(): AbstractList.java. Therefore, the above solution using simply asList() should be fine, at least when targeting JVM.
Instead of slicing, why don't you try just iterating over all the objects and getting the JSONObjects? I think this would be much more efficient.
fun JSONObject.obj(vararg names: String): JSONObject? {
var jsonObject = this
for (name in names) {
if (!jsonObject.has(name))
return null
jsonObject = jsonObject.getJSONObject(name)
}
return jsonObject
}

Kotlin Polymorphism Confusion

I was following a tutorial for learning kotlin and ran into this example.
open class AquariumPlant(val color: String, private val size: Int)
class GreenLeafyPlant(size: Int) : AquariumPlant("green", size)
fun AquariumPlant.print() = println("AquariumPlant")
fun GreenLeafyPlant.print() = println("GreenLeafyPlant")
val plant = GreenLeafyPlant(size = 10)
plant.print()
println("\n")
val aquariumPlant: AquariumPlant = plant
aquariumPlant.print() // what will it print?
Well this apparently prints "Aquarium Plant" instead of "GreenLeafyPlant". I was a bit confused by this so I tested this out with this little snippet of code.
open class Aquarium {
open fun printSize() {
println("hello")
}
}
class TowerTank: Aquarium() {
override fun printSize() {
println("rawr")
}
}
fun main() {
towerTank = TowerTank()
(towerTank as Aquarium).printSize()
}
So this prints "rawr" and not "hello". My question is why doesn't it print "hello"? Aren't these two examples contradicting themselves? How does the function extensions create this difference in behaviour? Sorry if this may seem like a dumb question, I'm new to Kotlin as you can probably tell.
To understand this we need to understand how extensions work. Extensions don't magically add new members to existing classes. This is technically impossible both in Java and Kotlin. Instead, they work as good old static utility functions in Java. Accessing them as members is just a syntactic sugar.
First example is really similar to these functions:
fun print(plant: AquariumPlant) = println("AquariumPlant")
fun print(plant: GreenLeafyPlant) = println("GreenLeafyPlant")
To make it even more clear, we can rename these functions:
fun printAquariumPlant(plant: AquariumPlant) = println("AquariumPlant")
fun printGreenLeafyPlant(plant: GreenLeafyPlant) = println("GreenLeafyPlant")
Now, it is pretty clear that if we have object like this:
val aquariumPlant: AquariumPlant = GreenLeafyPlant(size = 10)
Then we can only invoke printAquariumPlant() function with it and it will print AquariumPlant, not GreenLeafyPlant. Despite the fact aquariumPlant is actually a GreenLeafyPlant object.
If we move one step back and rename them again to just print, nothing will really change. aquariumPlant variable is of type AquariumPlant (even if it contains GreenLeafyPlant object), so the compiler chooses print(AquariumPlant) function.
This is why we say extensions are resolved statically. Compiler decides which function to call at compile time. Virtual functions are resolved at runtime, taking into consideration the real type of the object.

Kotlin arrow-kt, functional way to map a collection of either to an either of a collection

I've been using kotlin arrow quite a bit recently, and I've ran into a specific use case that has me stuck.
Let's say I have a collection of some object that I want to convert to another datatype using a convert function. Let's also say that this convert function has an ability to fail-- but instead of throwing an exception, it will just return an Either, where Either.Left() is a failure and Either.Right() is the mapped object. What is the best way to handle this use case? Some sample code below:
val list: Collection<Object> // some collection
val eithers: List<Either<ConvertError, NewObject>> = list.map { convert(it) } // through some logic, convert each object in the collection
val desired: Either<ConvertError, Collection<NewObject>> = eithers.map { ??? }
fun convert(o: Object) : Either<ConvertError, NewObject> { ... }
Essentially, I'd like to call a mapping function on a collection of data, and if any of the mappings respond with a failure, I'd like to have an Either.Left() containing the error. And then otherwise, I'd like the Either.Right() to contain all of the mapped objects.
Any ideas for a clean way to do this? Ideally, I'd like to make a chain of function calls, but have the ability to percolate an error up through the function calls.
You can use Arrow's computation blocks to unwrap Either inside map like so:
import arrow.core.Either
import arrow.core.computations.either
val list: ListObject> // some collection
val eithers: List<Either<ConvertError, NewObject>> = list.map { convert(it) } // through some logic, convert each object in the collection
val desired: Either<ConvertError, Collection<NewObject>> = either.eager {
eithers.map { convert(it).bind() }
}
fun convert(o: Object) : Either<ConvertError, NewObject> { ... }
Here bind() will either unwrap Either into NewObject in the case Either is Right, or it will exit the either.eager block in case it finds Left with ConvertError. Here we're using the eager { } variant since we're assigning it to a val immediately. The main suspend fun either { } block supports suspend functions inside but is itself also a suspend function.
This is an alternative to the traverse operator.
The traverse operation will be simplified in Arrow 0.12.0 to the following:
import arrow.core.traverseEither
eithers.traverseEither(::convert)
The traverse operator is also available in Arrow Fx Coroutines with support for traversing in parallel, and some powerful derivatives of this operation.
import arrow.fx.coroutines.parTraverseEither
eithers.parTraverseEither(Dispatcheres.IO, ::convert)
This is a frequent one, what you're looking for is called traverse. It's like map, except it collects the results following the aggregation rules of the content.
So, list.k().traverse(Either.applicative()) { convert(it) } will return Either.Left is any of the operations return Left, and Right<List< otherwise.
How about arrow.core.IterableKt#sequenceEither?
val desired: Either<ConvertError, Collection<NewObject>> = eithers.sequenceEither()

is there any way I send a nullable Function<T,R> as parameter in Kotlin?

I am trying to use the public interface Function (as I learned it in Java) in Kotlin.
For this I created my method
fun foo(input: List<String>, modifier1: Function<List<String>>? = null){
}
as far I remember here I should be able to do modifier1.apply(input)
but seems like it is not possible (it is possible to do modifier1.apply{input} though)
Reading more about it I found this:
Kotlin: how to pass a function as parameter to another?
So I changed my method signature to this:
fun foo(input:String, modifier2: (List<String>) -> (List<String>){
}
Here I am able to do modifier2(input)
and I can call foo this way
service.foo(input, ::myModifierFunction)
where
fun myModifierFunction(input:List<String>):List<String>{
//do something
return input
}
So far this seems possible but it is not acceptable to have the function reference as nullable, is there any way I can do that? or use Function ?
You were using kotlin.Function instead of java.util.function.Function in your first example. Note that the latter takes 2 generic types: 1 for the incoming parameter and 1 for the resulting one.
The apply method you saw is the default Kotlin one: apply, not the one of Java's Function-interface.
If you really want to have the Java-function as nullable type the following should work:
fun foo(input: List<String>, modifier1: java.util.function.Function<List<String>, List<String>>? = null) {
modifier1?.apply(input) ?: TODO("what should be done if there wasn't passed any function?")
}
Kotlin variant for the same:
fun foo(input: List<String>, modifier1: ((List<String>) -> List<String>)? = null) {
modifier1?.invoke(input) ?: TODO("what should be done if there wasn't passed any function?")
}
Maybe also a default function, such as { it } instead of null might better suite your needs? (Java variant would be Function.identity()):
// java modifier1 : Function<List<String>, List<String>> = Function.identity()
// kotlin modifier1 : (List<String>) -> List<String> = { it }
You can make the reference nullable simply with ? — the only wrinkle is that the whole function type needs to be in parens first:
fun foo(input: String, modifier2: ((List<String>) -> List<String>)? = null) {
}
As required, modifier2 is optional; if specified, it may contain null, or it may contain a function taking and returning a list of strings.
As mentioned in another answer, kotlin.Function is not the same as java.util.function.Function — though in practice you shouldn't need to refer to either directly, as the -> notation is simpler.
If you want to pass in a function that takes List<String> as its parameter and returns nothing meaningful, the type for you is Function1<List<String>, Unit>. The method name for invoking a function is invoke(), which you could also do with just regular parentheses, if it wasn't nullable. All in all, your code could look something like this:
fun foo(input: List<String>, modifier1: Function1<List<String>, Unit>? = null) {
modifier1?.invoke(input)
}
The 1 in the typename of Function1 means that it's a one parameter function, there's also Function0, Function2, etc.
The Function type on its own is not something you can use to call that function, as it's an empty marker interface. All functions implement this regardless of how many parameters they have.

Is there a simple null safe operator for Kotlin function references?

I'd like to pass a function reference on a nullable object. To take an Android example, say I want to use Activity#onBackPressed from a fragment that is a child of that actvity.
If I wanted to invoke this function, I could easily do
activity?.onBackPressed()
However, say I wanted to pass that as a reference instead:
val onBackPressedRef = activity::onBackPressed
This gives the familiar null safe error of Only safe or non null assserted calls are allowed...
I can get the error to go away with the following, but using !! is obviously not ideal:
val onBackPressedRef = activity!!::onBackPressed
Attemping activity?::onBackPressed was my first instinct, but this also breaks with several errors, where the interpreter seems confused.
val onBackPressedRef = activity?.let { it::onBackPressed }
This last variation works, but it's a lot more ugly than just using ?::. I checked all the docs I could find, but I feel like I'm missing something. Any ideas?
You are right, there is no ?:: operator in Kotlin.
You have several alternatives:
1. let and run
Thus, you have to use a helper function. Instead of let(), you can also use run(), making the expression a tiny bit shorter:
val onBackPressedRef = activity?.let { it::onBackPressed }
val onBackPressedRef = activity?.run { ::onBackPressed }
But keep in mind that either way, the invocation will be more verbose, too:
onBackPressedRef?.invoke(args)
Thus you should ask yourself, if this is really what you want, or if a no-op function call is also acceptable.
2. Closures
You could use a closure -- this will change semantics however:
val onBackPressedRef = { activity?.onBackPressed() }
Here, onBackPressedRef is not nullable anymore, so you can call it using the () operator, and in case of null activity it will have no effect.
3. Helper function
If function references with nullable objects are something you encounter a lot, you can write your own little abstraction:
// Return type: () -> Unit
fun <T> funcRef(obj: T?, function: T.() -> Unit) = { obj?.function() }
This trades a different syntax for a non-null function variable:
// activity can be null
val onBackPressedRef = funcRef(activity, Activity::onBackPressed)
// Callable directly
onBackPressedRef()