1

我正在尝试在 kotlin 中使用箭头

箭头具有三个功能

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

我想知道这些之间的区别。我知道 IO.fx 和 IO.fx {!effect} 帮助我们使用副作用,但是两者之间的区别是什么,为什么我要使用一个而不是另一个

4

1 回答 1

5

虽然这将很快改变,但在 0.11.X 版本上:

  • IO { }是一个带有挂起函数的构造函数,所以你可以在里面调用任何挂起函数。这是一条捷径IO.effect { }
suspend fun bla(): Unit = ...

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

fun otherIO(): IO<Unit> = IO.effect { bla() }
  • IO.fx { }IO除了增加了一些 DSL 函数,这些函数是 IO 的其他 API 的快捷方式外,其余相同。最重要的是!or bind,它在里面执行另一个 IO。
fun myIO(): IO<Unit> = IO.fx { bla() }

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

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

它启用的另一个功能是effect第一点的构造函数。所以你实际上正在做的是添加一个额外的包装层,这可能不是必需的。

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

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

我们经常inefficientUnpackedIO从访问支持渠道的人那里看到这一点,而且很容易被替换为IO { bla() }.

effect为什么在and中有两种方法可以做同样的事情fx?这是我们希望在下一个版本中改进的地方。我们建议尽可能使用最不强大的fx抽象,因此仅在使用其他IO基于 API(例如调度或并行化)时才保留。

IO.fx {
  val id = getUserIdSuspend()
  val friends: List<User> = 
    !parMapN(
      userFriends(id),
      IO { userProfile(id) },
      ::toUsers
    )
  !friends.parTraverse(IO.applicative()) { user ->
   IO { broadcastStatus(user) } 
  }
}
于 2020-08-31T20:08:39.120 回答