fused-effects icon indicating copy to clipboard operation
fused-effects copied to clipboard

Enable type-level distinctions between operations that thread state and those that don’t.

Open patrickt opened this issue 5 years ago • 10 comments

We removed the Resource effect in #268 because of its unlawful interactions with the State effect. This was the right move, but it is also a bummer, because the Resource effect is extremely useful.

What would be ideal is a system like polysemy’s Tactics module, which used in concert with Resource and the withLowerToIO system provided by their forklift implementation. Failing that, it would be ideal to have some type-level mechanism that rejects calls to functions like get and put inside a finally block:

finally :: (Has Resource sig, Carrier sig m, IsStatelessIn n m) 
  => m a
  -> n a
  -> m a

where this hypothetical IsStatelessIn construct is fulfilled by Reader but not by State. Or something. Either approach would be acceptable to me; that would enable us to deprecate fused-effects-exceptions and welcome Resource back into the fold.

patrickt avatar Oct 23 '19 18:10 patrickt

I was following along with some of the polysemy work on Tactics and Strategy and remembered some threads that may be useful if y'all end up going down that route:

@KingoftheHomeless discusses the Final and Lift' effects for embedding higher order effects

@KingoftheHomeless PR's these effects, along with the Strategy environment for making this higher-order effect weaving easier

Strategy and Final have since been merged into polysemy, but most of the history and discussion is in polysemy-zoo IIRC.

jkachmar avatar Oct 23 '19 19:10 jkachmar

Notably, asyncToIOFinal (which uses Strategy) obviates the need for all the Forklift machinery and so avoids the additional thread + polling machinery.

jkachmar avatar Oct 23 '19 19:10 jkachmar

I believe #296 gives us this capability.

robrix avatar Oct 25 '19 16:10 robrix

296 will close this, yes.

patrickt avatar Oct 25 '19 20:10 patrickt

So it looks like you said #296 would give us this capability but that PR was ultimately closed. I, like many others, are coming to this for the desire to be able to asyncify things that are effectively Identity wrappers. All the issues talking about this are dead-ended in some way. What's the state of the art knowledge on how to deal with this?

EDIT: the desire is to retain the ability to have multiple interpretations, none of them need to have state in the context functor though

ProofOfKeags avatar Oct 09 '20 22:10 ProofOfKeags

@ProofOfKeags At the risk of sounding full of myself, the state of the art on this would be the approach taken by my newly released library: in-other-words. One thing the approach does is that an interpreter may introduce constraints that restrict what other interpreters may be used together with it. This gives you what you're looking for: you can have an effect for concurrency, since its interpreter can place restrictions on what other interpreters you may use to guarantee that it's able to unlift to IO.

KingoftheHomeless avatar Oct 12 '20 10:10 KingoftheHomeless

@KingoftheHomeless Cool that you were able to solve this. Can't say I'm a fan of trying to switch effect systems as a result of this, but I may still attempt to do so at some point. I was hoping I'd be able to patch fused-effects or restrict myself to some subset of the library in order to do be able to use async effects.

ProofOfKeags avatar Oct 12 '20 19:10 ProofOfKeags

It’s possible we could take the same approach in fused-effects (haven’t looked into it yet), but failing that, it’s also possible to do what I’m doing in starlight & isometry and just… drop any state changes happening on the background thread.

That’s not ideal, and it’s regrettably silent, but it does allow for sensible use if you keep that in mind: basically, you get to make and observe any sort of local state changes you want in the forked thread, so long as you remember that they’re not going to be magically synchronized back to the forking thread.

Further, you can also use this sort of thing to set up some sort of synchronization mechanism to transport state changes across threads; I’m doing that in those projects, too.

So all is not lost!

robrix avatar Oct 12 '20 21:10 robrix

I think this is definitely superior to straight up not having a polymorphic async effect. I think a big warning on the tin that says that the pure construction of state/writer won't propagate over async effects is something that most people would have the capacity to understand.

ProofOfKeags avatar Oct 12 '20 23:10 ProofOfKeags

In fused-effects-exceptions there’s a carrier for State that uses an IORef and thus doesn’t lose information. We could add one for Writer as well.

patrickt avatar Oct 12 '20 23:10 patrickt