Comments (10)
Also, for what it's worth, I've had to define my own
newtype EventM' a = EventM' (EventM a)
deriving (Functor, Applicative, Monad)
because EventM
is a type synonym and thus cannot be partially applied in a type such as Auto EventM Event AppState
.
from brick.
I've checked in some changes that address your second comment (making EventM
a newtype
).
As for the first bit: I don't know anything about the auto
package so it isn't immediately obvious to me what changes in brick
would make it easier to integrate with auto
. I've taken a look at some different approaches to making halt
do what you want, and although I agree making it "return immediately" would be nice, I don't know of any approaches that would work at present. The issue is that the fact that EventM
can "halt" or "continue" is not related to the monad at all, but to the Next
type that is required to be returned by event handlers. So to make the monad capable of returning immediately, the "halt/continue/suspend-and-resume" features would need to be merged into the monad. My experiments suggested that the EventM
type would need to be tagged with the state type of the application to permit a "halt" operation to match the type of the state expected to be returned by the event handler (e.g. EventM s (Next s)
). But I think that is pretty messy, and adding such a type variable infects more innocent code than I'd like (and requires the type variable to be added to other types that don't have anything to do with it).
Without more information I don't think I can embark on a refactoring. I'm happy to consider patches if you have ideas on how to implement this.
from brick.
I haven't looked at the internals at all, but an API that seems more natural might be something like
data EventF a where
Halt :: EventF a
Suspend :: IO s -> (s -> a) -> EventF a
instance Functor EventF where ...
newtype EventM a = FreeT EventF (ReaderT (Map Name Viewport) (StateT EventState IO)) a
deriving (Functor, Applicative, Monad, MonadFree EventF, ...)
continue :: s -> EventM s
continue s = pure s
halt :: EventM a
halt = liftF Halt
suspend :: IO s -> EventM s
suspend action = liftF (Suspend action id)
-----
appHandleEvent :: s -> e -> EventM s
defaultMain :: App s e -> s -> IO ()
from brick.
Thanks for writing that up! halt
needs to be modified to take a state parameter of type s
since that's a requirement of the API. I'd also like to know whether there are any viable approaches that don't involve using free
.
from brick.
Ah, it was just a suggestion to allow you to move the Next
semantics from the return type into the monad, as you mention. What's wrong with free
if I may ask?
Alternatively - you could perhaps expose the Next
ADT in some public Internal
module. That'd suffice for my use case, although again, I can easily work around the problem by e.g. returning Just MyState
to indicate continue
, and Nothing
to indicate halt
.
from brick.
Here's a brick/auto adapter module from some work on a reddit client if you want to take a look. It's a bit kludgy and likely going to change eventually.
https://github.com/mitchellwrosen/reddit-cli/blob/master/src/Brick/Auto.hs
from brick.
I'd like to avoid exposing the internals of halt
, continue
, and suspendAndResume
since I'd like to hide the implementation details. My objection to free
is due to not understanding it, not being able to find any tutorials that clearly motivate it in this case, and wanting to avoid seemingly heavier abstractions where lighter ones will suffice (thus my desire for evidence that it is essential to a solution). If you can fill me in on this, that would be helpful!
Here's some extra context: my intention with the existing flow control API was to provide a mechanism for (only) the top-level event handler with the expectation that details about how to manage and compose event handling and state mutation would be a matter of doing pure operations rather than building up a library of EventM
actions. Put another way, I imagined that composition would be free because most event-handling code wouldn't be written in EventM
at all. I imagined most of it would be pure (except for handleEvent
) and that if an application has a more sophisticated notion of flow control, it could be implemented in any way necessary and embedded in (and translated to) the expectations of EventM
. I never intended for EventM
computations to be especially composable because of this mentality. This is also why I would shy away from using EventM
in a "return-immediately" imperative programming style since in my experience it has the potential to obscure event-handling logic and resist refactoring.
Thanks for linking to that demo module! That helps illuminate what you're dealing with in the auto/brick interaction. I guess if it were me doing it (again, speaking from a position of ignorance on auto), going on what I said above, I wouldn't write the Auto
values in terms of EventM
. It seems like that's the root cause of the need to instrument the rest of the API with the ability to deal with the results of the auto computations.
from brick.
Makes sense, and I'm definitely exploring this "imperative-ish" game-loop type world myself for the first time in Haskell. In fact, looking back over my code, I'm not yet even using auto
to its full potential, which is isolating stateful computations from each other. For that reason, I could have just used ordinary functions that mutate the global state... which is exactly what the original API is!.
For understanding free
, I recommend some of Gabriel Gonzalez's posts such as this one.
from brick.
Since it's been a while on this issue: is this a show-stopping problem for anything you need to do?
If not, I'd like to close this since I'm not inclined to make the change. I looked into free
and wrote some toy programs with it but I don't grok it well enough to feel comfortable integrating it into a core part of my library.
from brick.
Nope, it's not a show stopper by any means.
from brick.
Related Issues (20)
- row ... now exceeds region width HOT 8
- Is there any way to wait for an input? For example, wait for confirmation. HOT 8
- There should be something like `fmapState`. HOT 10
- Consider adding `zoomOut` for saving lines when dealing with sum types. HOT 3
- Cannot install `brick` via `cabal update && cabal install brick` on NixOS HOT 9
- Add version of customMain that doesn't require a Vty handle HOT 11
- Documentation Unavailable on Hackage HOT 4
- Can you add brick-trading-journal to featured projects on README? HOT 1
- Mouse-based selection stops working after using the mouse in an app. HOT 17
- Visbility request for FormFieldState instead of FormField HOT 7
- Segmentation fault when eagerly pressing a keyboard key HOT 3
- test compilation failure with brick-2.1.1 in Nixpkgs HOT 3
- How can I get SIGTSTP (ctrl-z) to suspend the process? HOT 6
- Thread blocked indefinitely in an STM transaction HOT 35
- Provide absolute coordinates on brick mouse event HOT 5
- Progress bar usage HOT 6
- How to use dialogSelection with appHandleEvent function? HOT 7
- Pop-up overlay dialog, is it possible? HOT 23
- Keybindings config character uppercase HOT 3
- Add keybindingINIList output to Brick.Keybindings.Pretty HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from brick.