-
Notifications
You must be signed in to change notification settings - Fork 169
Description
This ticket is a place for discussing the impact of work that is happening on the refactor/event-state-monad
branch. The objective of this branch is essentially to refactor EventM
to make event handler code more modular, easier to write, and less verbose. This branch introduces several breaking API changes.
If you write/maintain brick applications, I'd love your thoughts on how this will impact your applications (positively and negatively) if this were to be merged and released. I'd also love feedback if you actually try using the branch as well. Thanks!
Examples of the impact of these changes in action can be found in the demo programs. Here are a few examples:
Here's a summary of the changes and their impacts:
- The
EventM
type is changing fromEventM n a
toEventM n s a
.EventM n s a
is now aMonadState
overs
. (The state monad introduced in this change is strict ins
.) This means that you can either use lenses or themtl
state monad API to manage your state. Therefore, event handler functions that previously took an explicit state argument and returned aNext
are now state-monadic over that state type instead. For example, a function that was previously written ashandleMyEvent :: s -> BrickEvent n e -> EventM n (Next s)
will now be writtenhandleMyEvent :: BrickEvent n e -> EventM n s ()
. - The
Next
type is going away from the user-facing API. This meansEventM
blocks in event handlers no longer need to end withcontinue
,halt
, etc. Instead, the behavior previously provided by thecontinue
function is now the default behavior for anyEventM
block, andhalt
etc. need to be called explicitly to indicate what the library's main event loop should do once the event handler terminates. Functions likehalt
do not change control flow ofEventM
(i.e. do not cause early aborting). continue
itself was removed from the API. A practical consequence of this is that if anEventM
block now callshalt
, it cannot undo that by subsequently callingcontinue
sincecontinue
no longer exists.handleEventLensed
went away and has been replaced with support for thezoom
function frommicrolens-mtl
. This works with both lenses and traversals.Brick.Types
now re-exportszoom
for convenience.- The library's event handler functions (e.g. for
List
,Edit
, etc.) are now scoped to just the states they manage; e.g.handleEditorEvent :: BrickEvent n e -> EventM n (Editor t n) ()
. This means they are now used withzoom
, i.e.zoom someLens $ handleEditorEvent e
. This also impacted theForm
type whose field event handlers correspondingly changed to be scoped to their fields' state types. - Brick now depends on
mtl
rather thantransformers
.
To me, the biggest practical consequences of these changes are that:
- Positive:
EventM
code will be much cleaner, particularly if you like to use lenses to manage your state values. Event handlers can now use lens updates with themicrolens-mtl
API, e.g.,someLens .= someValue
etc. - Positive: Nested event handlers can now change state types, leading to more focused and more modular event handler implementations.
- Positive: event handlers will no longer have
continue
noise since that is the default behavior of anyEventM
block unless otherwise specified byhalt
etc. - Positive: brick application authors who want to use lenses more often in their event handlers can now do so.
- Positive: even brick application authors who don't want to use lenses more often can still benefit from the move to make
EventM
a state monad over the application state type. - Negative: Application authors will need to update their event handlers to use the new API. Depending on the application, this may be quite a bit of work. If this gets released, I'll provide upgrade guidance documentation.
- Negative: Applications that previously used their own event handler wrapper monads around
EventM
will have to contend with these changes as well. (I suspect this will be rare.)