Skip to content
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

Powerful interpretNew #399

Closed
wants to merge 2 commits into from
Closed

Conversation

KingoftheHomeless
Copy link
Collaborator

@KingoftheHomeless KingoftheHomeless commented Jan 4, 2021

A draft based on a draft? Pure madness.

This revamps the interface of interpretNew to the point it can cover almost all previous uses of interpretH. The only exception are the bad lower- interpreters, and if we really want, we can expand the interface to cover them too.

Despite its power, the interface is actually fairly simple: we manage to avoid exposing that MonadTransWeave is at play under the hood.

interpretNew has the type signature

interpretNew :: forall e r a
              . EffHandlerH e r
             -> Sem (e ': r) a
             -> Sem r a

where

type EffHandlerH e r = forall z t x. Traversable t => e z x -> Sem (RunH z t (e ': r) ': r) x

Which is only moderately scary. The interface associated with RunH are the functions:

-- Main function to run HO thunks
runH :: z a -> Sem (RunH z t (e ': r) ': r) a

-- Run a HO thunk, but don't automatically recursively run the current interpreter on it.
runH' :: z a -> Sem (e ': RunH z t (e ': r) ': r) a

-- Run a HO thunk and reify the local effectful state it results in
runExposeH :: z a -> Sem (RunH z t (e ': r) ': r) (t a)

-- The runH' equivalent of runExposeH
runExposeH' :: z a -> Sem (e ': RunH z t (e ': r) ': r) (t a)

-- Restore a reified effectful state
restoreH :: t a -> Sem (RunH z t (e ': r) ': r) a

runExposeH and restoreH is for all the effectful state manipulation some interpreters need to do in order to work correctly, such as runWriter.

Now the question is: is even this too complex? We can take measures to reduce the complexity: such as having Polysemy only export runH and runH', and having the other methods be part of a different module, say Polysemy.InterpretH or something, but the type of EffHandlerH is still somewhat scary -- on the same level as Tactical.

Unfortunately, I haven't found a way to simplify EffHandlerH further -- even if you try to only support runH and runH', I still can't figure out a way to get rid of the 2 extra type variables associated with RunH (although you can remove the Traversable constraint.)

@tek
Copy link
Member

tek commented Jan 4, 2021

I'd say that the tradeoff of the higher complexity of the outermost API over the consistency of the entire lib and the reduced complexity of Tactical is worth it. fresh users have a steep learning curve anyway and this might make it easier to produce some more holistic introductory docs.

@KingoftheHomeless
Copy link
Collaborator Author

Expanded the interface with two new methods: exposeH and getProcessorH. The latter allows me to get rid of the remaining uses of interpretH.

@isovector
Copy link
Member

Subsumed by #422. Closing, but feel free to open if you feel like it!

@isovector isovector closed this Oct 19, 2021
@tek tek deleted the interpreth-powerful branch September 23, 2023 12:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants