Closed refaelsh closed 1 year ago
There are a couple of things going on here. First, the type error you reported is because the type of the then
branch of the if
does not match the required type of the overall function, handleEvents
, which must evaluate to EventM String State ()
. To fix this, both branches of the if
must have evaluate to that type. Right now, the branches currently have types EventM String State (Editor String String, ())
and EventM String State (TerminatorState, ())
, respectively.
Here's how to think about nestEventM
: it takes some value and allows you to work on that value as the state in the context of an EventM
block. It then returns the possibly modified state as well as the EventM
block's result. You're then responsible for putting the resulting modified state back where it belongs in your overall application state. (This may seem a bit involved, but if it does, that's the reason why the lens-based API exists. I know you said you don't want to use that API quite yet, and that's okay; but I wanted to point this out.)
Both of your if
branches need to take care of storing the modified state they operate over. (As an aside, the then
branch currently does nothing to the editor that it is given. Not sure if that's your intention.) In addition, the terminatorState
use in the else
branch will later fail to type-check because that state isn't the state that's needed to run handleEditorEvent
. You'd need an Editor
as the EventM
state for that to work. Your then
branch is closer to what you'd need to get that working.
A fix for the then
branch would look something like:
if x < 3
then do
(newEditor, ()) <- nestEventM (bricksEditor (terminatorState state)) $ do
handleEditorEvent someEvent
modify $ \s -> s { terminatorState = terminatorState s { bricksEditor = newEditor } }
A couple of other comments:
State
and TerminatorState
, but you don't need GADTs for those types. Just plain old data
will do, e.g.
data State =
State { bricksList :: List String String
, bricksFocusRing :: FocusRing String
, terminatorState :: TerminatorState
}
theApp
above.Thank you, thank you very much! I will read it thoroughly and try to understand. I will close this non-issue in the meantime.
(As an aside, the then branch currently does nothing to the editor that it is given. Not sure if that's your intention.)
Yes, it is my intention.
ou're using GADTs for State and TerminatorState, but you don't need GADTs for those types
Yea, I figured that much. Its just that I am using Haskell LSP and by default it sugests to use GADTs and then my OCD kicks in...
recommend you update your coding style to put commas on the beginnings of lines as I did in the above declaration. You'll see that convention used in almost all Haskell code that you come across.
Yes yes. The default of the LSP is not like this. I have a menatl note to change the settings (if it is even possible).
Four space indents are much more common in Haskell code than two spaces.
modify $ \s -> s { terminatorState = terminatorState s { bricksEditor = newEditor } }
Is there any particular reason for modify
instead of put
?
(This may seem a bit involved, but if it does, that's the reason why the lens-based API exists. I know you said you don't want to use that API quite yet, and that's okay; but I wanted to point this out.)
Yes yes, I am still in the early stages of Haskell Indocrination, so I will avoid lenses for the foreseeable future.
"much more common" - it is a strong statement.
I suppose it is; it's just true in my experience, having been working in Haskell for about 15 years. If nothing else, it's what I use in all of my libraries and applications and it's what I prefer for readability.
Is there any particular reason for modify instead of put?
I think it's just that I wrote my example without seeing your get
; in that case I'd recommend using put $ state { ... }
instead since you already did a get
. Usually I think about doing modify
instead if at all possible because it avoids the problem of getting mixed up with other intermediate results from get
and then put
ting the wrong one. It also helps write code in a more functional style since you can just pass a modification function to modify
.
Hope that helps!
I've read it like 10 times. I undestand now. I managed to make my code work with the help of your answer. Thank you very much :-)
Great, I'm glad to hear it!
Here is an MRE I extracted from my actual code:
Here is the error:
Please help :-)