Open 1Jajen1 opened 5 years ago
Ping me If you start working on this @1Jajen1 :)
excellent thanks, also ping me, interested in the direction this takes
@1Jajen1 I'm not sure if you looked at FreeC which is like Free
but it also deals with unexpected occurring errors.
@raulraja I am assuming we still want to upgrade this to arrow-free
at some point. We discussed once to replace Free
with FreeC
if this is still the plan than maybe this is the issue where we clean up FreeC
and promote it to arrow-free
and replace Free
.
Thoughts?
I don't really like that tbh. I think that overcomplicates Free and it is not really necessary imo. Baking in error handling in Free looks wrong. Not doing so might also be more performant when thinking about church encoding. Error handling can be done using FreeT or explicitly. Either way FreeC will also directly benefit from a different approach to Free (recursion schemes as foldMap, better coproducts and deriving Functors + docs).
Also can't FreeC be expressed as monad transfomers over Free or other way around by using FreeT? That may be a cleaner approach to free. I'd love to see a direct comparison so I'll do FreeT first and check how that all works out
Well, @1Jajen1 FreeC
was originally built as a foundation for Stream<F, A>
, where this additional power is needed. I'm fine with keeping it internal in arrow-streams
but I still think it's valuable to expose for others.
We can also decide to expose both. Having the possibility to move Free
to FreeC
with the same utilities etc is probably also an advantage.
EDIT: For sure you could express FreeC
with FreeT
and get MonadError
/Concurrent
instances but this comes at a perf cost which is not desired for use cases like Stream
or similar use cases.
Is anything happening here?
From a slack thread: https://kotlinlang.slack.com/archives/C5UPMM0A0/p1554022508033000 Right now there are several weird things around the Free-monad: (when I refer to Free later on I mean the Free-Monad)
Some of these approaches could also directly benefit other parts of arrow, especially auto-deriving stuff (although I think there needs to be a discussion regarding generating code using kapt with reference to multiplatform use before). And also arrow-streams may benefit from it.
Some more in-depth parts:
injectL (F) -> CoproductPartialOf<F, G>
orinjectR (G) -> CoproductPartialOf<F, G>
is trivial and going further with nested coproducts also is. We can generate code for something like aFreeMonadContinuation<F, G, ...>
that allows callingbind
on anyFree<F, A>
(beforehand for some reasonable depth or maybe in kapt at compile time). Same for interpreters over Coproducts.a
as some sort of continuation (the first example I wrote in the slack thread does that) and you instantly get typesafety back all the way. With smart constructors this is also invisible from the user.MonadError
. That can get you pretty far I think. Another approach if you simply want to short-circuit on error is wrappingFree
inEitherT
, but that is very limited. Yet another approach isFreeT
, now there are other good reasons to useFreeT
, but for now I'll focus on errors. WithFreeT m
simply provide aMonad m
that also is aMonadError
and delegate error handling to that (at least I think thatFreeT
isMonadError
whenm
isMonadError
This all really is more of a discussion and task-list, I also think it has little priority for now, but I did not want to loose the opportunity to write this down before the slack thread gets long forgotten :)
I'll probably tackle some of these in the upcoming months, but will explicitly write here when I do, so if anyone is interested in doing part of this feel free to do so!
@i-walker @raulraja I think this covers most of what we were talking about, if not feel free to add stuff here :)