I would like to improve the REPL experience in two ways:
- Currently it reevaluates all bindings in your session on every expression submitted. That is, it bundles up a new module with everything in it and runs a fresh node process. This makes it problematic if you want to support effectful bindings. Currently you cannot run effectful code and use the result in subsequent expressions. You can use
unsafePerformEffect, but that will run your effects again and again. I would like to run a persistent node process for the entire repl session rather than a process to evaluate each expression.
- There’s no way to run async code. Once we allow effectful code to run, it would be nice to support running
Aff, where the repl will block until a result is received.
purs repl code to manage this node process, and likely changing how it invokes the compiler, so that it can grab and submit the individual bindings to the evaluator instead of a module with everything in it. Additionally it would have to know how to extract the type of an evaluated expression and retain that in the type environment.
For the second case, I would like to change the signature of the
Eval code to return an
Aff-like signature instead of
Effect Unit, and also return the evaluated type. Something like
eval :: forall a b. Eval a b => -- The value to evaluate (Unit -> a) -> -- The callback to invoke if an exception occurs (Error -> Effect Unit) -> -- The callback to invoke with evaluated value `b` (b -> Effect Unit) -> -- Returns a canceller, which will cleanup whatever is running when invoked Effect (Effect Unit)
I’ve prototyped something like this in my evaluator, and doesn’t seem to be an issue.
Would anyone like to collaborate on this? Do other PureScript maintainers or users have any opinions on these changes?