The new 'suspend' API is very interesting. I start...
# arrow
p
The new 'suspend' API is very interesting. I started to write some pieces of code ... But, to go further in my investigations, the absence of typeclass disturbs me: how to write a polymorphic program? I missed something between Async/ApplicativeError and suspend datatypes ! I understand: if I want to play with F, ..., i need to build datatypes over fxcoroutine. Is the right way ?
r
There is currently no type classes for suspend since suspend can subsume all the Functor hierarchy. So suspend on it’s own is polymorphic.
A suspend program can run in different runtimes and currently there exists a single pure FP lib for suspend that is Fx Coroutines.
So if you want to be parametric to F it already works like that with the current Kind Encoding. If you have a kinded program and that kinded program has monad you have its monad Fx block
But in the near future that is not necessary
because ContT or the equivalent @simon.vergauwen and I are working on for suspend can lift any suspend computation into any arbitrary monad also suspended even interleaving it.
This means no need for kinds, transformers etc and type classes can just be expressed in terms of suspend or pure methods as simple interfaces without the double nesting.
If you noticed the Fx coroutines library does not have map, flatMap and others and it’s because they are pointless if you have direct style.
They are only needed for the indirection to put things into a box but suspension removes that indirection since suspend programs are like free monad programs, they can be target any datatype for wich a suspension runtime exists.
For example SequenceBuilder in the std lib is a suspension runtime for the Sequence data type
kotlinx coroutines is a lightweight future based runtime for a datatype Deferred
And Arrow Fx coroutines only needs to provide concurrent operators to complete the laws of IO
suspend is F
Arrow Fx coroutines provides a full runtime with concurrency for something we did not consider IO before which is Suspend<A> or
suspend () -> A
the reason why Functor is not needed is because the compiler turns that automatically into
(Continuation<A>) -> Unit
so the indirection is removed for the user.
j
because ContT or the equivalent @simon.vergauwen and I are working on for suspend can lift any suspend computation into any arbitrary monad also suspended even interleaving it.
Are you planning to encode monads in cps style, use the continuation like our current encoding to call
flatMap
on suspend or go a different route and straight up for effects and handlers? All of those are possible with
ContT
so just wondering 🙂 Also is there a link/repo/branch to check? I am quite interested in the inner workings there 😅
r
hi Jannis, we have been exploring many different encodings to be able to remove Kind all around. They all fail with the same issue which is advancing the continuation because of the reset problem but we are close to crack single shot multiprompt instead of multishot which is what we need
but a lot has been removed over history
that one is based on Roman’s encoding for shift reset
j
Ah yeah multishot is quite annoying I guess 😅 But it's sadly very very necessary
Especially for nondet carriers
r
In that last link I sent we can see how we are suspending and advancing over completion and we just need to push a new prompt
j
I should also probably clarify: I am also interested in how
ContT
itself is implemented, but there are also many ways to encode monads and effects on top of continuations, so what is the idea there?
r
which is what I’m trying to figure out now. Simon is working in a similar encoding based Monad Reflect
The idea here is that we can bind in place ad hoc for non deterministic monads like streams and lists that require multiprompt
currently we have a version for other monads that does no need the reflection tricks
j
So similar to our current fx encoding but without the hacks?
r
but those still do unless we push new shifted prompt bodies
yes
no hacks all multiplatform and interleaving allows you bind in place multiple effects
so basically create transformer blocks too
j
What type would such a composed computation return?
r
all computations are suspended so they are direct but interleaved ones would look like this:
Copy code
val List<Either<Error, A>> = 
  interleaved<List<*>, Either<Error, *> {
    val a = listOf(...)()
    val b = either()
    a + b 
  }
In pseudocode and unfinished syntax
essentially since we are suspending we can bind more than one type in the same block if there is just and flatMap evidence for them
The issue we have with ContT as encoded in haskell or Scala is that in place bind is not possible because it lifts the entire block to the monad
but we need to bind in the middle of the block and suspend
j
haskell's contT is also pretty slow as an abstraction isn't it? And I don't really think scala will be any faster
Hmm will interleaved be available for any (sensible) arity? And also are there ideas/plans of going for something different than monads like algebraic effects?
I am asking because if not I'll definitely give it a shot at some point 😅 There are a few things that I want to try with a fast
ContT
implementation: Mainly effects and parser combinators though 🙂
Could also make an interesting bachelors thesis 🤔
r
definetly, we are not sure yet how interleaved would work but we know since now in this impl we have control of suspension since the first reset we can compute arbitrarily inside. The challenging part is still pushing prompts in the middle of the body
If you want to help I’m happy to talk over what we tried and the issues we found and were we are at
We are trying several approaches in parallel including ContT which we disregarded because in place bind has the same problem there than a fast mutable stack based runtime
j
If you have some papers or references on continuation implementations that'd be great. I've been poking your branch a bit, but I think I need some more formal understanding first 🙂
That gist contains a thread with relevant links and topics, once Loom lands this is a non problem because Loom can suspend natively and statically pinning to the current thread
but with the current model of CPS the Kotlin compiler that we need to push new prompts for non deterministic monads like List
that is a barebone primitive impl of shift/reset which is not even in Scala
but it’s single prompt in our case because our bind needs to happen in the block so the link in my branch is modified suspend version that tracks the stack states on each relevant step in the log and advanced and accumulates completions (in progress)
p
Great explanation thx. So, Functor typeclass could be expressed as a simple interface with a suspended map. Interesting point of view... i need to reformat my mind to see this new perspective ! As I understand it, integration layers like reactor / rx could also have their implementation with a direct syntax around their suspended context.
r
Yes, any library can write a suspend runtime, kotlinX Coroutines is one, Arrow Fx another and nothing stops a library author to optimice their libs with it. In the case of Rx and others they need multiprompt for Stream but the fact we already have fx extensions for Rx shows they could have had suspended based Rx impl. Streams and single could be bound in place for imperative syntax without chaining flatMap as people frequently use Rx.
p
About delimited continuation: @raulraja and @Jannis, did you see this GIST (just updated by Roman) https://gist.github.com/elizarov/5bbbe5a3b88985ae577d8ec3706e85ef
r
Yes I participated in the combo with Roman and Jonathan. We started from something similar and tried many encodings. The issue with that one for our use case is multiprompt on nondet like lists or streams where we have to shot inside the block and rewind more than once. @Jannis figured out some magic for internals of shift to allow it to shot more than once and we are iterating over it now.
Also Jonathan has great encodings and papers on this concept in other languages including a new lang he developed based on Scala and effect handlers
I don’t see recent updates to the gist @PhBastiani did i miss something?
p
Last active 9h ago... But yes no update
👍 1