make repl more extensible #121
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
All tests passed.
The 4 commits include in order:
clean
Collect the action functions from
Main.leanto their own source files, along with their related message and response definitions.polymorphism
MonadREPLand related instances to provide the REPL effects, that is, command&proof snapshots manipulation.M := StateRefT State IOand itsMonadREPLinstance.The main advantage is
StateRefTbeing much more performant thanStateT. The trade-off isMbeing specialized toIO, otherwise we would add many confusingSTWorldstuff in the signature of effectful functions.This makes sense since some existing actions really specialize (hard-coded) to
IOand thus provide no polymorphism. Why not get it straight?For the originally polymorphic functions with
[Monad m] [MonadLiftT IO m], we add[MonadREPL m]to qualifymand returnm adirectly rather than wrap it inM m a. Under this setting, users can still make their own monad, implementMonadREPLfor it, and call the polymorphic functions on it.error handling
ResultT m := ExceptT Error mlocal instance [ToJson e] [toJson a] : ToJson (Except e a)Compared to the present manual error handling with sum-type, the new scheme will enable early-return and much more readable error handling in effectful actions.
Remark: The
catchconstruct provided by Lean 4 supports dispatch by explicit exception type. Thus, we can still handlecatch ex : IO.ErrorinResultT mwhenever[MonadLiftT IO m]is satisfied.frameworking
Define two attributes
repl_requestandrepl_request_handlerto decouple request definition and handling from the main dispatch loop.This design is completely based on compile-time code generation, thus is statically safe, and induces no runtime overhead.
The following is the definition and handler of
Command:The new command
#mkInput InputinMain.leangenerates the definition of typeInputas well as itsFromJson Inputinstance. The instance handles the try-chain so we don't need to put them manually inparse.The main loop will then use an effectful macro
make_repl_dispatch% inputto parse a value of typeInput, call the corresponding handler, and return (monadically) the result json. The generated code is designed to be compatible in any monadic environment, and can be made pure inIdmonad.