I'm making a canvas game using PureScript and I'm wondering what the best way to handle event listeners is, particularly running the callbacks within a custom monad stack. This is my game stack...
type BaseEffect e = Eff (canvas :: CANVAS, dom :: DOM, console :: CONSOLE | e)
type GameState = { canvas :: CanvasElement, context :: Context2D, angle :: Number }
type GameEffect e a = StateT GameState (BaseEffect e) a
What I'd like to do is change the "angle" property in the GameState when any key is pressed (just for development purposes so I can tweak the graphics). This is my callback function...
changeState :: forall e. Event -> GameEffect e Unit
changeState a = do
modify \s -> s { angle = s.angle + 1.0 }
liftEff $ log "keypress"
pure unit
However addEventListener and eventListener look like they're meant to be used only with Eff, so the following won't type check...
addEventListener
(EventType "keypress")
(eventListener changeState)
false
((elementToEventTarget <<< htmlElementToElement) bodyHtmlElement)
I thought I could define addEventListener and eventListener myself and import them using the foreign function interfaces (changing Eff to GameEffect). That typed checked, but caused a console error when I tried running in the browser.
foreign import addEventListener :: forall e. EventType -> EventListener e -> Boolean -> EventTarget -> GameEffect e Unit
foreign import eventListener :: forall e. (Event -> GameEffect e Unit) -> EventListener e
What's the best way to handle running callbacks within a monad stack?