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.

Reply via email to