Hi team! I have a question around delimited contin...
# arrow
m
Hi team! I have a question around delimited continuations. Context: I’m trying to use arrow continuation to convert the ergonomics of an internal data structure that I have in some internal project. It’s somewhat a kleisli, which shape looks like the following:
Copy code
data class ExecutionPlan<out A>(val runPlan: suspend (PlanConfig) -> A) {
  fun <B> flatMap(fn: (A) -> ExecutionPlan<B>): ExecutionPlan<B> = ...

  // map, zip, traverse
  // etc...
}
Prior to arrow 0.13 it was leveraging
ExecutionPlan.monad().fx { … }.fix()
Now that is not available anymore and I’ve refactored the code to nested flatMaps.. which proliferated in the codebase, and is causing some pain..
Copy code
// what we have now:
val plan = planA.flatMap { a ->
  planB.flatMap { b ->
    planC(a, b).flatMap { c ->
      // ...
    }
  }
}

// what we want:
val plan = executionPlan { 
  val a = planA.bind()
  val b = planB.bind()
  val c = planC(a, b).bind()
  c
}
I’m wondering how i might leverage delimited continuation to implement this?
Copy code
fun interface ExecutionPlanEffect<E, A> : Effect<ExecutionPlan<A>> {
  suspend fun <B> ExecutionPlan<B>.bind(): B = ???
}
thanks!!
s
Hey Mitchell, It absolutely looks like it is possible, and quite easily looking at the signatures. I have some questions though, how is
flatMap
implemented?
Copy code
data class ExecutionPlan<out A>(val runPlan: suspend (PlanConfig) -> A) {
  fun <B> flatMap(fn: (A) -> ExecutionPlan<B>): ExecutionPlan<B> =
  ExecutionPlan { config ->
    val a = runPlan(config)
    fn(a).runPlan(config)
  }
}
If this is the case, than you can very easily implement a
executionPlan
Effect DSL.
Copy code
class ExecPlanSyntax(val config: ConfigPlan) {
  suspend fun <A> ExecutionPlan<A>.bind(): A = runPlan(config)
}
And I assume there is a function like this to run the
ExecutionPlan
.
Copy code
operator fun <A> ExcutionPlan<A>.execute(plan: PlanConfig): A = fn(ExecutionPlan(plan), plan)
Now we can update our constructor to incorporate our DSL, and rewrite
flatMap
using suspension.
data class ExecutionPlan<out A>(val runPlan: suspend ExecPlanSyntax.(PlanConfig) -> A)
Copy code
ExecutionPlan {
  val a = bind()
  val b = f(a).bind()   
}
Hope that helps @mitch. Happy to help, but perhaps easier to collaborate over code.
m
Oh man that's absolutely genius! Thanks @simon.vergauwen!!! I'll give that a shot
👍 1