使用协程在 kotlin 中的列表上实现 monad 理解

问题描述

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

举个例子:

Notification notification = new NotificationCompat.Builder(context,"notifyOrg@l").setSmallIcon(R.mipmap.task)
                .setContentTitle(title)
                .setContentText(description)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setAutoCancel(true)
                .setContentIntent(resultPendingIntent)
                .build();

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

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

Arrow-Kt 使用 either,nullable,option and eval 的协程定义了类似的推导式。我查看了实现及其 Effect documentation,但无法将概念转换为列表。这在 kotlin 中甚至可能吗?

解决方法

目前无法为 List、Flow 和其他发出多个值的非确定性数据结构实现 monad comprehension。 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 暂停或延续提供无需重播当前块的情况下进行多重射击的能力之前它是不安全的。或者,我们需要 real for comprehensions 或类似的结构来强制绑定发生在其他代码之前,这也可以解决块重放问题。

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