-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Effect Monad Instance #559
Comments
Another case where Let's say we have some function like this:
right now there is no convenient way for me to "call" this saga and get its result. If I I can manually create and iterate over the generator to collect the return value, but this is a pretty bad solution to the problem. EDIT: Upon further research I discovered that |
Any thoughts here? Really all this issue is asking for is the |
Every redux-saga/src/internal/proc.js Line 307 in 238b394
return ed. You would need to implement runRunEffect in similar way that other 'runners' are implemented.
Also you would have need to implement Line 75 in 238b394
yield ed effect in an object so it can be interpreted later by runEffect in proc.js .
Although I dont quite grasp this - " |
Example:
It looks like it might not be so easy given that |
Ok, I guess I see the difference with to which saga forks are attached, however I have no idea whats the purpose, beside monad wizardry ;) not saying that its worthless, just dont see a personal attraction to it right now.
Still aint sure though what did u mean with 'never get here', |
|
Cant find that behavior nor in the docs nor in the source code, im on Such behavior seems to me at least weird. Did u check if it rly behaves |
It looks like it is covered here https://redux-saga.github.io/redux-saga/docs/advanced/ForkModel.html. |
Thanks for pointing that out, had no idea this works like that, fortunately never had urge to call forking task :) In that case your |
Reopening this as I would like to spend some more thought on it and explore the idea, which truth to be told is not so easy for me to grasp as thinking about monads is really a brainburner when one is not accustomed to it. However your example of: export function* doBackground(saga, config) {
const handle = yield fork(backgroundTask(saga, config));
return handle;
} Seems like a legitimate use case. One should be able to call it somehow in non-blocking manner and get the Maybe some @yelouafi what were your thoughts about this? you probably get a lot more about this as you are more familiar with functional concepts Your requested |
So originally I phrased this all in Monad language because I thought it would be helpful to have some context to refer to, but it seems to have caused more confusion than clarity. This issue is mostly a feature request for The "Monad wizardry" is mostly just recognizing that using |
So, I would like to implement this one way or another, but aint sure when yet. Still I won't merge it in until @yelouafi comes back and have time to comment on the matter. Dont take me wrong - 'monad wizardry' isnt something bad in mi eyes and I think that it was certainly helpful from your side to include this reasoning etc. Its just me who is not too familiar with these concepts (yet :P)
why they would be then and are not now? |
A Monad is just a type that fulfills a few criteria, mainly that there exists a set of functions
If you refer back to my original post you will see my attempts at providing implementations of For more info (in haskell though): https://en.wikipedia.org/wiki/Monad_(functional_programming)#Monad_laws |
In JavaScript, a lot of FP types are implemented according to the Fantasyland spec, which essentially just gives us standard names for common operations and provides chainable APIs. Conforming to Fantasyland would allow for interoperability with a whole bunch of JS libraries. See the Fantasyland Monad spec. |
@ericelliott Yeah, I know about the spec and ofc would like to follow it if possible, but for now there are more pressing issues in the library than this and also this is a little over my head at the moment. Would need to study a little bit more about monads to understand it and implement properly. |
After a long discussion with @WuTheFWasThat about what this should look like, I think I have something coherent to share:
We would like to be able to think about sagas using an
Effect
monad. Let's start by giving some example types:given these we can try to write a
Monad
instance forEffect
:so close! These functions appear to work, and have the correct type signatures, but their behavior is wrong in the presence of fork. One of the monad laws is that
bind(instance, pure) === instance
. It's important to follow these laws so that the behavior of monad combinators is clear and consistent.First lets write
fork
in a way more friendly to thinking about things as just pureEffect
creators:Now lets try to apply our combinators to it:
We now expect that
runSomeEffect
andshouldBeTheSame
are the same, but they aren't!runSomeEffect
has the expected behavior of runningsomeEffect
in the background, butshouldBeTheSame
will run it in the foreground (or at least wait for it to complete).One way to solve this issue is to introduce a new effect,
run
, which is likecall
except that it runs the given saga in the context of the current saga. Normally we useyield*
to accomplish this, but you can'treturn yield* something
as a pure value the same way you can returncall(something)
as a pure value. With run, we'd be able to returnrun(something)
as a pure value.Then we can write our Monad instance like so:
and when we try to use them like before, we now get the correct behavior.
In conclusion I think the addition of
run
would allow more useful saga combinators to be written clearly and consistently by allowing us to write a correct monad instance for Effect.The text was updated successfully, but these errors were encountered: