Yeah I've been looking for potentially a way to have 2 message types altogether. I am leaning toward just Msg having an UpdateMsg and a FilterMsg subtypes. It would be easy to split on either then and even hoist them into their request function.
On Wednesday, August 10, 2016 at 11:51:36 AM UTC-6, Janis Voigtländer wrote: > > Okay, saw this only after sending my previous message. Still, the > FilterOnly message to be handled in update functions now is like a return > of the NothingHappened message that I was so happy to have eliminated. > Plus, the filters function’s added complexity. I still stand with “I’d > rather have the Keyboard API changed in the way I proposed, than to have > to use this more complicated machinery.” > > > 2016-08-10 19:38 GMT+02:00 OvermindDL1 <[email protected] <javascript:>>: > >> It would need the HandleKeyboardDown/Up messages, however I've recently >> made a change to my Msg structure so I have something like this: >> ```elm >> >> type alias MsgFiltered = >> { HandleKeyboardUp Char >> , HandleKeyboardDown Char >> } >> type alias Msg >> = FilterOnly MsgFiltered >> | Other >> | Interesting >> | To >> | Update >> | Messages >> | Like >> | JumpDown >> | JumpUp >> >> ``` >> And it seems to be working well. I just ignore the `FilterOnly` message >> entirely in my Update and can handle `FilterOnly` messages in the filter >> with ease (while still filtering others if I want). It makes it easy to >> add messages that are only converted to others in the filter, then just >> subscribe to `(\c -> FilterOnly (TestFiltered c))` as normal. That way you >> do not need to even have a case for them in your main update, just for the >> FilterOnly one, which you can just `( model, Cmd.none )` once. >> >> >> On Wednesday, August 10, 2016 at 11:22:47 AM UTC-6, Janis Voigtländer >> wrote: >>> >>> What will the GameMsg type look like? >>> >>> >>> 2016-08-10 18:59 GMT+02:00 OvermindDL1 <[email protected]>: >>> >>>> > If there are alternatives *with currently available functions* to my >>>> proposal, very interested to hear it in this thread. >>>> >>>> That is why I looked at more options and started thinking about how it >>>> could also solve other filtering issues that I have, so a singular thing >>>> that could solve it all would be nice. :-) >>>> >>>> >>>> Given code from the dontfall game, the current top-post suggestion was >>>> to change subscriptions to be: >>>> ```elm >>>> >>>> subscriptions : GameData -> Sub GameMsgsubscriptions d = >>>> Sub.batch >>>> ([ Keyboard.downsSelectively (\c -> if Char.fromCode c == 'P' then >>>> Just PauseToogle else Nothing) ] ++ >>>> if d.state == Running then >>>> [ AnimationFrame.diffs Tick >>>> , Keyboard.downsSelectively (\c -> if Char.fromCode c == ' >>>> ' then Just JumpDown else Nothing) >>>> , Keyboard.upsSelectively (\c -> if Char.fromCode c == ' ' >>>> then Just JumpUp else Nothing) >>>> ] >>>> else >>>> []) >>>> >>>> ``` >>>> >>>> In the thing I proposed that can handle generic message filtering (not >>>> just subscription) would turn the above back into a fairly normal and >>>> readable style of: >>>> ```elm >>>> >>>> subscriptions : GameData -> Sub GameMsgsubscriptions d = >>>> Sub.batch >>>> [ Keyboard.downs HandleKeyboardDown >>>> , Keyboard.ups HandleKeyboardUps >>>> , if d.state == Running then AnimationFrame.diffs Tick else Sub.none >>>> ] >>>> >>>> ``` >>>> And a new callback (added in the main where init/update/etc are, in my >>>> package is called 'filters') would be something like this, this is a very >>>> simple example and `filters` can do a lot more, but for simple keyboard >>>> filtering: >>>> ```elm >>>> >>>> filters : Msg -> Model -> ( Msg, States Model Msg )filters msg model = >>>> if model.state == Running then >>>> case msg of >>>> HandleKeyboardDown c -> >>>> case Char.fromCode c -> >>>> 'P' -> ( PauseToggle, States.enableAll ) >>>> ' ' -> ( JumpDown, States.enableAll ) >>>> _ -> ( msg, States.disableAll ) >>>> HandleKeyboardUp c -> >>>> case Char.fromCode c -> >>>> ' ' -> ( JumpUp, States.enableAll ) >>>> _ -> ( msg, States.disableAll ) >>>> _ -> ( msg, States.enableAll ) >>>> else >>>> ( msg, States.enableAll ) >>>> >>>> ``` >>>> You could also delegate to other TEA-style modules. You could filter >>>> out the Tick here instead of subscribing and unsubscribing (I like a >>>> simple >>>> 'subscriptions' callback). Anything with `States.disableAll` will disable >>>> all callbacks for that msg, so update will not be called, subscriptions >>>> will not be called, and view will not be called (it returns the cached >>>> values from last time so an exact match test of === in javascript shows >>>> they are identical and thus Elm will do nothing). >>>> >>>> With the above `filters` you will not ever get >>>> HandleKeyboardDown/HandleKeyboardUp in your `update` at all, ever, it is >>>> either translated to another message or entirely canceled. Adding more >>>> message conversions is as simple as adding another case, so you could add, >>>> say a shooting state with like: >>>> ```elm >>>> >>>> filters : Msg -> Model -> ( Msg, States Model Msg )filters msg model = >>>> if model.state == Running then >>>> case msg of >>>> HandleKeyboardDown c -> >>>> case Char.fromCode c -> >>>> 'P' -> ( PauseToggle, States.enableAll ) >>>> ' ' -> ( JumpDown, States.enableAll ) >>>> 'z' -> ( StartShooting, States.enableAll ) >>>> _ -> ( msg, States.disableAll ) >>>> HandleKeyboardUp c -> >>>> case Char.fromCode c -> >>>> ' ' -> ( JumpUp, States.enableAll ) >>>> 'z' -> ( StopShooting, States.enableAll ) >>>> _ -> ( msg, States.disableAll ) >>>> _ -> ( msg, States.enableAll ) >>>> else >>>> ( msg, States.enableAll ) >>>> >>>> ``` >>>> >>>> Just as simple as adding a readable case to each the down and up to >>>> send the two StartShooting/StopShooting messages. You could easily pull >>>> values from the model if the user can remap their keys and just do if's >>>> instead too. >>>> >>>> But yes, the filtering of messages is done in one and only area, and if >>>> you filter everything well then your update does not even need to become a >>>> mess of nested case's for the various states and such but you know that >>>> you >>>> will only get a message when it is actually valid for your state, so you >>>> know that you will not get a, say, `JumpUp` message unless you are in the >>>> `Running` state, so you do not even need to check that. Your operations >>>> become simple and direct. >>>> >>>> >>>> On Wednesday, August 10, 2016 at 10:27:42 AM UTC-6, Janis Voigtländer >>>> wrote: >>>>> >>>>> Generally, Nick is right, I primarily want to hear feedback about the >>>>> specific API proposal I made. >>>>> >>>>> However, I wrote the other day that "If there are alternatives *with >>>>> currently available functions* to my proposal, very interested to >>>>> hear it in this thread." >>>>> >>>>> So since Overmind seems to since have released some package/functions >>>>> that are now available, it could be on-topic to see how/whether these do >>>>> address points I try to address with the API proposal. Hence my questions >>>>> (or "challenge" if you wish) in the previous message. >>>>> >>>>> >>>>> 2016-08-10 18:13 GMT+02:00 Nick H <[email protected]>: >>>>> >>>>>> That is not what this discussion is about. Janis proposed a change to >>>>>> the Keyboard API. The reason he started this thread was to get our >>>>>> thoughts >>>>>> on his proposal. >>>>>> >>>>>> On Wed, Aug 10, 2016 at 8:37 AM, OvermindDL1 <[email protected]> >>>>>> wrote: >>>>>> >>>>>>> How is it off-topic considering its whole purpose is to handle this >>>>>>> exact kind of issue? The discussion is about filtering messages, >>>>>>> potentially translating them to a a better message that is for a >>>>>>> specific >>>>>>> purpose without needing to worry about checking for valid input in >>>>>>> update >>>>>>> area. It is handled generically. >>>>>>> >>>>>>> >>>>>>> On Wednesday, August 10, 2016 at 8:44:12 AM UTC-6, Nick H wrote: >>>>>>>> >>>>>>>> Overmind, we can all see the thread that you started. It is still >>>>>>>> off-topic for you to bring it up here. >>>>>>>> >>>>>>>> On Wed, Aug 10, 2016 at 7:40 AM, OvermindDL1 <[email protected]> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> Well for what it is worth I made a library that can filter >>>>>>>>> messages before they are handled, so you could, for example, turn a >>>>>>>>> keypress of 'w' into a message of 'GoForward' and 's' into >>>>>>>>> 'GoBackward' or >>>>>>>>> whatever. And if you cancel a message then it becomes entirely >>>>>>>>> unhandled >>>>>>>>> and you will never even see it appear in the event loop >>>>>>>>> (update/subscription/view). If your convert a message then you never >>>>>>>>> see >>>>>>>>> the original, only your converted one. I am curious if anyone wants >>>>>>>>> to >>>>>>>>> test it with these issues as I think it would work very well as a, >>>>>>>>> for >>>>>>>>> example, key remapper. It is a nice-central place to put key mapping >>>>>>>>> (since it has a model you could even setup a dynamic key mapper based >>>>>>>>> on >>>>>>>>> user settings with ease). Cleans up code in update as since you can >>>>>>>>> expect >>>>>>>>> to only receive valid messages if you filter them here first, vastly >>>>>>>>> cleans >>>>>>>>> up code there to only the actual work. The package is up at the elm >>>>>>>>> package website (ProgramEx I think I named it). Still very in >>>>>>>>> testing but >>>>>>>>> it seems to be working utterly perfect in one of my big apps and has >>>>>>>>> already cleaned up a lot of code. Here is how the filter code looks >>>>>>>>> (this >>>>>>>>> one 'delegates' to two different TEA-form libraries their messages >>>>>>>>> and >>>>>>>>> alters a Scroll event just like you'd expect to do with key >>>>>>>>> remapping): >>>>>>>>> >>>>>>>>> ```elm >>>>>>>>> >>>>>>>>> filters : Msg -> Model -> ( Msg, States Model Msg )filters msg model = >>>>>>>>> let >>>>>>>>> log = >>>>>>>>> debug_log (model.programFlags.debug_log |> >>>>>>>>> Maybe.withDefault False) "filters" ( msg, model ) >>>>>>>>> in >>>>>>>>> case msg of >>>>>>>>> Helpers helpersMsg -> >>>>>>>>> ( msg >>>>>>>>> , States.enableAll |> States.delegate >>>>>>>>> (helpers_delegate Helpers helpersMsg) >>>>>>>>> ) >>>>>>>>> >>>>>>>>> Mdl mdlMsg -> >>>>>>>>> ( msg >>>>>>>>> , States.enableAll >>>>>>>>> |> States.delegate >>>>>>>>> { key = "Mdl" >>>>>>>>> , update = Just (\_ o -> Material.update >>>>>>>>> mdlMsg o) >>>>>>>>> , subscriptions = Just (\o -> >>>>>>>>> Material.subscriptions Mdl o) >>>>>>>>> } >>>>>>>>> ) >>>>>>>>> >>>>>>>>> >>>>>>>>> MesgList_Scroll scrolled -> >>>>>>>>> case model.loc of >>>>>>>>> RoomLocation rid _ -> >>>>>>>>> let >>>>>>>>> doLoad : Bool >>>>>>>>> doLoad = >>>>>>>>> (model.firstMessageReached == False) >>>>>>>>> && (scrolled.pos < 16) >>>>>>>>> && (model.isLoadingOlder == False) >>>>>>>>> >>>>>>>>> && ((Dict.size >>>>>>>>> model.active_room_msgs) >= 10) >>>>>>>>> >>>>>>>>> in >>>>>>>>> if doLoad then >>>>>>>>> ( MesgList_LoadOlder rid, >>>>>>>>> States.enableAll ) >>>>>>>>> else >>>>>>>>> ( msg, States.disableAll ) >>>>>>>>> >>>>>>>>> _ -> >>>>>>>>> ( msg, States.disableAll ) >>>>>>>>> >>>>>>>>> >>>>>>>>> _ -> >>>>>>>>> ( msg, States.enableAll ) >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> >>>>>>>>> On Tuesday, August 9, 2016 at 10:55:43 PM UTC-6, Nick H wrote: >>>>>>>>>> >>>>>>>>>> This would be a really nice improvement. I doubt there is anybody >>>>>>>>>> using the keyboard API who wants to capture every key press. (But >>>>>>>>>> would >>>>>>>>>> love to see a counter-example!) Typing is handled by the HTML library >>>>>>>>>> >>>>>>>>>> On Mon, Aug 8, 2016 at 11:01 PM, Janis Voigtländer < >>>>>>>>>> [email protected]> wrote: >>>>>>>>>> >>>>>>>>>>> To up the proposal, here a revision. >>>>>>>>>>> >>>>>>>>>>> Instead of proposing to *add* new functions, I now propose to >>>>>>>>>>> *replace* >>>>>>>>>>> >>>>>>>>>>> Keyboard.presses : (KeyCode -> msg) -> Sub msgKeyboard.downs : >>>>>>>>>>> (KeyCode -> msg) -> Sub msgKeyboard.ups : (KeyCode -> msg) -> Sub >>>>>>>>>>> msg >>>>>>>>>>> >>>>>>>>>>> by >>>>>>>>>>> >>>>>>>>>>> Keyboard.presses : (KeyCode -> Maybe msg) -> Sub msgKeyboard.downs >>>>>>>>>>> : (KeyCode -> Maybe msg) -> Sub msgKeyboard.ups : (KeyCode -> Maybe >>>>>>>>>>> msg) -> Sub msg >>>>>>>>>>> >>>>>>>>>>> It would still be easy to recover the old behavior if wanted in >>>>>>>>>>> a specific situation, by throwing in Just. But actually I posit >>>>>>>>>>> that one almost never really wants to capture all keys. Usually, >>>>>>>>>>> one wants >>>>>>>>>>> to be selective. That selectiveness has to be expressed somewhere, >>>>>>>>>>> and >>>>>>>>>>> doing it with the Maybe type that is designed for such purpose >>>>>>>>>>> is generally better than going for something like extra NoOp or >>>>>>>>>>> NothingHappened or NotBound constructors that then need to be >>>>>>>>>>> handled in a special way in the app’s update logic, without help >>>>>>>>>>> from the >>>>>>>>>>> type system. Making consideration of the selectiveness part of the >>>>>>>>>>> modelling up front would lead to better design. That’s at least the >>>>>>>>>>> case in >>>>>>>>>>> the projects/repositories I have pointed to. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> 2016-08-08 14:48 GMT+02:00 Janis Voigtländer < >>>>>>>>>>> [email protected]>: >>>>>>>>>>> >>>>>>>>>>>> A while back there was a thread >>>>>>>>>>>> <https://groups.google.com/d/msg/elm-discuss/u-6aCwaJezo/fu-HMPy6CQAJ> >>>>>>>>>>>> >>>>>>>>>>>> about filtering subscriptions. The following is related, but can >>>>>>>>>>>> also (and >>>>>>>>>>>> probably better) be consumed and discussed independently. For >>>>>>>>>>>> those that do >>>>>>>>>>>> have that older thread as context in mind, the following differs >>>>>>>>>>>> in two >>>>>>>>>>>> essential ways: >>>>>>>>>>>> >>>>>>>>>>>> - Earlier, the discussion was about generic filtering of >>>>>>>>>>>> arbitrary subscriptions. The following involves no genericity >>>>>>>>>>>> whatsoever. >>>>>>>>>>>> It is only a proposal about the Keyboard API specifically. >>>>>>>>>>>> - The earlier thread was not rooted in practice, since very >>>>>>>>>>>> little stuff had been built yet with subscriptions. In the >>>>>>>>>>>> following, I >>>>>>>>>>>> point to how things have played out in practice, based on uses >>>>>>>>>>>> students >>>>>>>>>>>> have made of the current API in projects. >>>>>>>>>>>> >>>>>>>>>>>> ------------------------------ >>>>>>>>>>>> >>>>>>>>>>>> So, on to the subject matter: >>>>>>>>>>>> >>>>>>>>>>>> The keyboard package >>>>>>>>>>>> <http://package.elm-lang.org/packages/elm-lang/keyboard> >>>>>>>>>>>> currently contains functions such as: >>>>>>>>>>>> >>>>>>>>>>>> Keyboard.downs : (KeyCode -> msg) -> Sub msg >>>>>>>>>>>> >>>>>>>>>>>> Common uses (I’ll point to several repositories below) are such >>>>>>>>>>>> that only some keys are relevant for an application. My proposal >>>>>>>>>>>> is to have >>>>>>>>>>>> functions such as: >>>>>>>>>>>> >>>>>>>>>>>> Keyboard.downsSelectively : (KeyCode -> Maybe msg) -> Sub msg >>>>>>>>>>>> >>>>>>>>>>>> where the semantics is that if a given KeyCode is mapped to >>>>>>>>>>>> Nothing by the tagger, then no message gets sent along the >>>>>>>>>>>> subscription; otherwise the Just is peeled off and the message >>>>>>>>>>>> gets sent. >>>>>>>>>>>> ------------------------------ >>>>>>>>>>>> >>>>>>>>>>>> Let’s look at a practical case, >>>>>>>>>>>> https://github.com/arpad-m/dontfall. It’s a game, where the >>>>>>>>>>>> player uses the keyboard for part of the control. Important >>>>>>>>>>>> excerpts from >>>>>>>>>>>> the code are: >>>>>>>>>>>> >>>>>>>>>>>> The message type (in >>>>>>>>>>>> https://github.com/arpad-m/dontfall/blob/master/src/BaseStuff.elm >>>>>>>>>>>> ): >>>>>>>>>>>> >>>>>>>>>>>> type GameMsg = NothingHappened | ... several other messages ... >>>>>>>>>>>> >>>>>>>>>>>> The subscriptions definition (in >>>>>>>>>>>> https://github.com/arpad-m/dontfall/blob/master/src/main.elm): >>>>>>>>>>>> >>>>>>>>>>>> subscriptions : GameData -> Sub GameMsgsubscriptions d = >>>>>>>>>>>> Sub.batch >>>>>>>>>>>> ([ Keyboard.downs (\c -> if Char.fromCode c == 'P' then >>>>>>>>>>>> PauseToogle else NothingHappened) ] ++ >>>>>>>>>>>> if d.state == Running then >>>>>>>>>>>> [ AnimationFrame.diffs Tick >>>>>>>>>>>> , Keyboard.downs (\c -> if Char.fromCode c == ' ' >>>>>>>>>>>> then JumpDown else NothingHappened) >>>>>>>>>>>> , Keyboard.ups (\c -> if Char.fromCode c == ' ' >>>>>>>>>>>> then JumpUp else NothingHappened) >>>>>>>>>>>> ] >>>>>>>>>>>> else >>>>>>>>>>>> []) >>>>>>>>>>>> >>>>>>>>>>>> The main case distinction in the main update function (in >>>>>>>>>>>> https://github.com/arpad-m/dontfall/blob/master/src/main.elm): >>>>>>>>>>>> >>>>>>>>>>>> updateScene : GameMsg -> GameData -> (GameData, Cmd >>>>>>>>>>>> GameMsg)updateScene msg d = >>>>>>>>>>>> (case d.state of >>>>>>>>>>>> ... >>>>>>>>>>>> Running -> case msg of >>>>>>>>>>>> MouseMove (x,_) -> { d | characterPosX = min x >>>>>>>>>>>> d.flWidth} >>>>>>>>>>>> Tick t -> stepTime d t >>>>>>>>>>>> PauseToogle -> { d | state = Paused } >>>>>>>>>>>> JumpDown -> { d | jumpPressed = True } >>>>>>>>>>>> JumpUp -> { d | jumpPressed = False } >>>>>>>>>>>> _ -> d >>>>>>>>>>>> , Cmd.none >>>>>>>>>>>> ) >>>>>>>>>>>> >>>>>>>>>>>> Given availability of the functions I propose above, the code >>>>>>>>>>>> could instead look as follows: >>>>>>>>>>>> >>>>>>>>>>>> type GameMsg = ... only the other messages, no NothingHappened ... >>>>>>>>>>>> subscriptions : GameData -> Sub GameMsgsubscriptions d = >>>>>>>>>>>> Sub.batch >>>>>>>>>>>> ([ Keyboard.downsSelectively (\c -> if Char.fromCode c == >>>>>>>>>>>> 'P' then Just PauseToogle else Nothing) ] ++ >>>>>>>>>>>> if d.state == Running then >>>>>>>>>>>> [ AnimationFrame.diffs Tick >>>>>>>>>>>> , Keyboard.downsSelectively (\c -> if >>>>>>>>>>>> Char.fromCode c == ' ' then Just JumpDown else Nothing) >>>>>>>>>>>> , Keyboard.upsSelectively (\c -> if Char.fromCode >>>>>>>>>>>> c == ' ' then Just JumpUp else Nothing) >>>>>>>>>>>> ] >>>>>>>>>>>> else >>>>>>>>>>>> []) >>>>>>>>>>>> updateScene : GameMsg -> GameData -> (GameData, Cmd >>>>>>>>>>>> GameMsg)updateScene msg d = >>>>>>>>>>>> (case d.state of >>>>>>>>>>>> ... >>>>>>>>>>>> Running -> case msg of >>>>>>>>>>>> MouseMove (x,_) -> { d | characterPosX = min x >>>>>>>>>>>> d.flWidth} >>>>>>>>>>>> Tick t -> stepTime d t >>>>>>>>>>>> PauseToogle -> { d | state = Paused } >>>>>>>>>>>> JumpDown -> { d | jumpPressed = True } >>>>>>>>>>>> JumpUp -> { d | jumpPressed = False } >>>>>>>>>>>> , Cmd.none >>>>>>>>>>>> ) >>>>>>>>>>>> >>>>>>>>>>>> Advantages: >>>>>>>>>>>> >>>>>>>>>>>> 1. >>>>>>>>>>>> >>>>>>>>>>>> simpler message type, no special role no-op constructor >>>>>>>>>>>> needed >>>>>>>>>>>> 2. >>>>>>>>>>>> >>>>>>>>>>>> no spurious update and render cycles while the game is >>>>>>>>>>>> running >>>>>>>>>>>> 3. >>>>>>>>>>>> >>>>>>>>>>>> less room for bugs in the update logic >>>>>>>>>>>> >>>>>>>>>>>> Some additional comments on the latter two of these points: >>>>>>>>>>>> >>>>>>>>>>>> Re 2., given the current implementation, whenever a key is hit >>>>>>>>>>>> that is not relevant, the update function is still called and >>>>>>>>>>>> produces an >>>>>>>>>>>> unchanged model, which is then rendered, which is extra/useless >>>>>>>>>>>> work. Since >>>>>>>>>>>> the game uses Graphics.*, no use can be made of Html.Lazy.* to >>>>>>>>>>>> avoid the re-rendering. Even if something like Graphics.Lazy.* >>>>>>>>>>>> were available, having to use it would not be as nice/pure as not >>>>>>>>>>>> causing >>>>>>>>>>>> those spurious updates in the first place. >>>>>>>>>>>> >>>>>>>>>>>> Re 3., given the current implementation, there is both more >>>>>>>>>>>> room for bugs in the now and in a potential later, when extending >>>>>>>>>>>> the game. >>>>>>>>>>>> In the now, the programmer has to make sure that >>>>>>>>>>>> NothingHappened does indeed not change the model. Concerning >>>>>>>>>>>> later, imagine that the programmer extends the message type for >>>>>>>>>>>> some >>>>>>>>>>>> reason. With the current version of updateScene, the >>>>>>>>>>>> programmer might forget to actually add a branch for handling the >>>>>>>>>>>> new >>>>>>>>>>>> message, and the compiler would not catch that, because of the _ >>>>>>>>>>>> -> d branch that will silently catch not only NothingHappened >>>>>>>>>>>> but also the new message which was actually supposed to make >>>>>>>>>>>> something >>>>>>>>>>>> happen. With the version of updateScene after the proposed >>>>>>>>>>>> change, the situation would be different. Since there is no _ >>>>>>>>>>>> -> d branch in that Running -> case msg of ... part anymore >>>>>>>>>>>> (thanks to NothingHappened not being a thing), the compiler >>>>>>>>>>>> will immediately complain if the message type is extended but the >>>>>>>>>>>> new >>>>>>>>>>>> message is not handled there. Bug prevented. >>>>>>>>>>>> ------------------------------ >>>>>>>>>>>> >>>>>>>>>>>> It’s not only this single project. I have observed students >>>>>>>>>>>> applying different strategies to deal with “Not all keys are >>>>>>>>>>>> relevant to my >>>>>>>>>>>> program”. In each case, using an API with functions of type >>>>>>>>>>>> (KeyCode >>>>>>>>>>>> -> Maybe msg) -> Sub msg instead of (KeyCode -> msg) -> Sub msg >>>>>>>>>>>> would have been conceptually nicer and would have simplified >>>>>>>>>>>> things. >>>>>>>>>>>> >>>>>>>>>>>> Some more example repos: >>>>>>>>>>>> >>>>>>>>>>>> - https://github.com/chemmi/elm-rocket, uses type Key = >>>>>>>>>>>> Left | Right | ... | NotBound and keyBinding : KeyCode -> >>>>>>>>>>>> Key and then needs to make sure to correctly (non)-deal >>>>>>>>>>>> with NotBound in functions like updateKeyDown; whereas just >>>>>>>>>>>> not having NotBound, but having keyBinding : KeyCode -> >>>>>>>>>>>> Maybe Key and using that in a call to a (KeyCode -> Maybe >>>>>>>>>>>> msg) -> Sub msg function would simplify things with the >>>>>>>>>>>> same benefits as in the above more fully elaborated example >>>>>>>>>>>> case. >>>>>>>>>>>> - https://github.com/Dinendal92/Abschlussprojekt-DP2016, >>>>>>>>>>>> less complete project, but with same approach and issues as in >>>>>>>>>>>> the >>>>>>>>>>>> preceding example, using type Key = Space | Unknown and >>>>>>>>>>>> fromCode >>>>>>>>>>>> : Int -> Key. Here, since eliminating Unknown would turn Key >>>>>>>>>>>> into a type with only one constructor, even more conceptual >>>>>>>>>>>> simplifications >>>>>>>>>>>> would be enabled after a switch to the (KeyCode -> Maybe >>>>>>>>>>>> msg) -> Sub msg approach. >>>>>>>>>>>> - https://github.com/Shaomada/Elm-Project, quite elaborate >>>>>>>>>>>> project, structured according to TEA, uses no special Key >>>>>>>>>>>> type, instead maps with Char.fromCode in the calls to the >>>>>>>>>>>> keyboard subscriptions, then has to case dispatch on actual >>>>>>>>>>>> Chars at several places distributed over the update >>>>>>>>>>>> functions of the TEA subcomponents. Subscribing with (KeyCode >>>>>>>>>>>> -> Maybe msg) -> Sub msg functions should allow to >>>>>>>>>>>> eliminate branches at some of those places, removing >>>>>>>>>>>> redundancies and room >>>>>>>>>>>> for bugs. >>>>>>>>>>>> - https://github.com/Sulring/elmaction, similar story >>>>>>>>>>>> (without TEA) >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>> Google Groups "Elm Discuss" group. >>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>> it, send an email to [email protected]. >>>>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>> Groups "Elm Discuss" group. >>>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>>> send an email to [email protected]. >>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "Elm Discuss" group. >>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>> send an email to [email protected]. >>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>> >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "Elm Discuss" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to [email protected]. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>> >>>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Elm Discuss" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to [email protected]. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "Elm Discuss" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
