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.lean
to their own source files, along with their related message and response definitions.polymorphism
MonadREPL
and related instances to provide the REPL effects, that is, command&proof snapshots manipulation.M := StateRefT State IO
and itsMonadREPL
instance.The main advantage is
StateRefT
being much more performant thanStateT
. The trade-off isM
being specialized toIO
, otherwise we would add many confusingSTWorld
stuff in the signature of effectful functions.This makes sense since some existing actions really specialize (hard-coded) to
IO
and 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 qualifym
and returnm a
directly rather than wrap it inM m a
. Under this setting, users can still make their own monad, implementMonadREPL
for it, and call the polymorphic functions on it.error handling
ResultT m := ExceptT Error m
local 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
catch
construct provided by Lean 4 supports dispatch by explicit exception type. Thus, we can still handlecatch ex : IO.Error
inResultT m
whenever[MonadLiftT IO m]
is satisfied.frameworking
Define two attributes
repl_request
andrepl_request_handler
to 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 Input
inMain.lean
generates the definition of typeInput
as well as itsFromJson Input
instance. 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% input
to 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 inId
monad.