【问题标题】:implement a monad comprehension on a list in kotlin using a coroutine使用协程在 kotlin 中的列表上实现 monad 理解
【发布时间】:2021-04-14 00:50:18
【问题描述】:

我想知道是否可以在具有单子属性的列表或类似列表的结构上实现类似于 Kotlin 中 Haskell 的 do-notation 的东西。

举个例子:

fun <A, B> cartesianProduct(xs: List<A>, ys: List<B>): List<Pair<A, B>> =
  xs.flatMap { x -> ys.flatMap { y -> listOf(x to y) } }

如果我能写出类似的东西就好了

suspend fun <A, B> cartesianProduct(xs: List<A>, ys: List<B>): List<Pair<A, B>> =
  list { 
    val x = xs.bind()
    val y = xs.bind()
    yield(x to y)
  }

Arrow-Kt 使用协程为 either, nullable, option and eval 定义了类似的理解。我查看了实现及其Effect documentation,但我无法将概念转换为列表。这在 kotlin 中是否可行?

【问题讨论】:

    标签: kotlin kotlin-coroutines arrow-kt


    【解决方案1】:

    目前还不可能实现对 List、Flow 和其他发出多个值的非确定性数据结构的 monad 理解。当前在 Kotlin 中的延续实现只是单一的。这意味着延续可以使用单个发出的值来恢复程序。多次恢复程序需要使用反射劫持延续堆栈标签,以便在第二次恢复时重放它们的状态。此外,重播绑定了多重数据类型的块将重播绑定之前的所有效果,因为该块必须再次发射。

    list {
      println("printed 3 times and not cool")
      val a = listOf(1, 2, 3).bind()
      a
    }
    

    arrow-continuations 库已经包含一个 MultiShot delimited scope for reset/shift,但它目前是内部的,因为在 Kotlin 暂停或延续提供多重处理而不重播当前块的能力之前它是不安全的。或者,我们需要真正的理解或类似的结构来强制绑定发生在其他代码之前,这也可以解决块重放问题。

    Effect 接口最终会委托给这些范围之一来实现它。 Reset.suspendedReset.restricted 的当前版本是单发的。

    【讨论】:

    • 感谢这个非常棒的解释!你是什​​么意思“真正的理解”?你能指出一些我可以查到的提示吗?
    • 嗨 Chris,真正的 for comprehensions 就好像它在像 Scala 这样的语言中,或者 Kotlin for 循环将是表达式而不是语句。作为一种语言结构,它们强制绑定按顺序执行。在 Kotlin 延续模型和具有延续(如 Loom monad)的模型中,bind 可以实现为函数,而不需要编译器经常重写为 flatMap、map 或类似的“for”样式理解形式的语言构造。
    猜你喜欢
    • 2022-11-02
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2019-07-16
    • 2021-04-30
    相关资源
    最近更新 更多