https://kotlinlang.org logo
#arrow-contributors
Title
# arrow-contributors
j

Jannis

11/06/2019, 7:21 PM
Hi, I am finally getting around to finishing the
Schedule
datatype that will enable users to easily express all sorts of retry/repeat strategies and I am at the point of choosing where to add the retry/repeat methods. Since the whole thing involves delay I was thinking Async or above (using
delay
from coroutines), but then I saw the
Timer
interface which offers some sort of sleep method for
Concurrent
and some other implementations for rx2 and reactor. So the question is, where does this go in the typeclass hierarchy?
r

raulraja

11/06/2019, 7:22 PM
@simon.vergauwen is changing that soon so he may be interested in reading this
👌 1
s

simon.vergauwen

11/07/2019, 8:26 AM
Hey @Jannis, Happy to see you again! Some extra info on tyhe typeclasses: -
Timer
is a separate typeclass because
Async
is not needed for a datatype to
sleep
. -
Concurrent
can derive
Timer
, so all it’s syntax is enabled in
Concurrent
typeclass and it has a
timer()
function that returns the derived instance. I’ll try to take a good look @ the
Schedule
PR asap, and we can discuss further there.
j

Jannis

11/07/2019, 12:36 PM
Thanks :) Currently the schedule pr only includes the schedule itself which is merely an effectful function that computes the next delay and whether or not to continue. It needs to be implemented on something that can be delayed for the delay returned by the schedule. My first guess was monad defer and above but that means using monad defer will get you blocking delay which is almost certainly not what most ppl want.
s

simon.vergauwen

11/09/2019, 12:01 PM
Nope, my initial thought is that you’ll need
Timer
+
Monad
which you already have from
MonadDefer
.
I was just wondering a bit about the design. I think it can be done a bit simpler with just an ADT which you interpret when you run it with an extension like. That’s a common approach since you can define any arbitrary pure ADT and interpret it to any
F
using typeclasses. That means you can have a more general
Schedule
which is not bounded to
F
.
Copy code
fun <F, A> Kind<F, A>.retry(schedule: Schedule, T: Timer<F>, M: Monad<F>: Kind<F, A> = ...

fun <F, A> Kind<F, A>.retry(schedule: Schedule: C: Concurrent<F>): Kind<F, A> = retry(schedule, C.timer(), C)
👍 1
Here is an example of a Kotlin library that takes the same approach. https://github.com/47deg/kollect/blob/master/kollect-core/src/main/kotlin/kollect/Kollect.kt#L137
That’s how I would approach it but I need to check ZIO again to figure out what operators are needed.
j

Jannis

11/09/2019, 7:30 PM
The schedule itself needs a monad, but that can be any. I am a bit worried about type inference when building schedules, that is already not so great, but I'll see what I can do. Implementing retry and repeat should be done over any kind, that's a great suggestion, thanks :) I'll add something to the pr tomorrow
s

simon.vergauwen

11/09/2019, 7:31 PM
Why does it need Monad?
Is
Schedule
not just a data type that defines how to retry? Even if it needs to run any effects to calculate the next retry you could defer that and run that effect within
F
using the typeclasses, no?
Or am I missing something?
j

Jannis

11/09/2019, 8:27 PM
Sorry I missed the notification on this thread
Some combinators need flatMap, map, just etc iirc. So to cacluate the next decision monad might be needed.
Combining is the problem, because there might be effectful computation embedded that need to be combined, hence we need something for F and there is at least one flatMap in there so monad. It does not need to be fixed right away if you don't use it, however that might hurt type inference
Schedule is best described as a (possibly) effectful function that produces a decision which describes how to continue, if at all, and the next state for the schedule
What we could do tho is define everything in schedule over id and generalize it to any monad when someone needs to embed some effect in there, which only a few combinators do
4 Views