Thinking of the Monad instance of List, will there...
# arrow
j
Thinking of the Monad instance of List, will there be such computation in arrow 0.12 (list comprehension) ?
r
Hi @Jörg Winter, There will be no monad comprehensions for List, Flow and in general non-deterministic monadic types that can emit more than one value because in the following scenario the effects in the block get replayed:
Copy code
list {
  println("I get printed 3 times")
  listOf(1, 2, 3).bind()
}
We do have a Multishot delimited scope implementations that is flagged as
internal
in
arrow-continuations
ready for when compiler plugins are supported both with the new IR and IR backends and there is a strategy for compiler plugins in the IDE. Hopefully sometime in between 1.5 and 1.7+. At that point Arrow meta can expose a compiler plugin that verifies that monad binding in non-deterministic monads is reinterpreted so that can instrument the block to split it an ensure the effects before suspension points are not played more than once.
In essence direct imperative bind in non deterministic monads requires a coroutines runtime for continuations that is multi-shot but Kotlin’s suspension system is single shot.
y
@raulraja could there maybe possibly be an
impure
block that you can call inside any multi-shot comprehension like list so that this impure block is only called once? this block can possibly be an extension on a new
ImpureScope
class that just has a boolean to tell the impure block whether to run or not. The
ImpureScope
could then be passed in as another receiver. I know that this isn't an elegant solution per se but it can allow people meanwhile to use comprehensions for these types and also for people who don't want to use compiler plugins
r
it still leads to incorrect code because regardless of suspension you can still perform side effects like println(), mutation etc. If you can’t enforce the user to follow it they won’t follow it. Transactions could rerun and things like that, it’s too much of a risk to make it generically available but we will revisit when compiler plugins are available in which case we can enforce it that all binds are first and effects don’t run more than once. In the meantime if you want to play with it and you have specific questions I’ll be happy to help. https://github.com/arrow-kt/arrow/blob/master/arrow-libs/core/arrow-continuations/src/test/kotlin/generic/TestSuite.kt#L20 In practice the most productive path for Arrow would be to start writting the Meta compiler plugin that validates blocks happening inside the MultishotDelimitedScope to not perform effects before binds, that is if in a block there is a bind then these binds need to all appear before other expressions (potentially effects).
once a compiler plugin validates that then it can safely run the block over the runtime of the MultishotDelimContScope
But before doing that we need a set of sample programs and what we expect as result when we do things like List bind.