Difference between Kotlin arrow IO, IO.fx, IO !effect

510 Views Asked by At

I am trying to use arrow in kotlin

Arrow has three functions

IO {}
IO.fx {}
IO.fx { !effect}

I want to know the difference between these. I know IO.fx and IO.fx {!effect} help us use side effects but then whats the difference between the two and why would I use one over the other

1

There are 1 best solutions below

0
On BEST ANSWER

While this is going to change shortly, on version 0.11.X:

  • IO { } is a constructor that takes a suspend function, so you can call any suspend function inside. It's a shortcut for IO.effect { }
suspend fun bla(): Unit = ...

fun myIO(): IO<Unit> = IO { bla() }

fun otherIO(): IO<Unit> = IO.effect { bla() }
  • IO.fx { } is the same as IO except it adds a few DSL functions that are shortcuts for other APIs of IO. The most important one is ! or bind, which executes another IO inside.
fun myIO(): IO<Unit> = IO.fx { bla() }

fun nestIO(): IO<IO<Unit>> = IO.fx { myIO() }

fun unpackIO(): IO<Unit> = IO.fx { !myIO() }

Another function it enables is the constructor effect from the first point. So what you're effectively doing is adding an additional layer of wrapping that may not be necessary.

fun inefficientNestIO(): IO<IO<Unit>> = IO.fx { effect { bla() } }

fun inefficientUnpackedIO(): IO<Unit> = IO.fx { !effect { bla() } }

We frequently see that inefficientUnpackedIO from people who come to the support channels, and it's easily replaceable by just IO { bla() }.

Why have two ways of doing the same in effect and fx? It's something we're looking to improve on the next releases. We recommend using the least powerful abstraction wherever possible, so reserve fx only when using other IO-based APIs such as scheduling or parallelization.

IO.fx {
  val id = getUserIdSuspend()
  val friends: List<User> = 
    !parMapN(
      userFriends(id),
      IO { userProfile(id) },
      ::toUsers
    )
  !friends.parTraverse(IO.applicative()) { user ->
   IO { broadcastStatus(user) } 
  }
}