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.”
>
Given this, how would that balloon the API for something like `onScroll` to 
only handle when it is in certain areas (like the top/bottom to load more 
things)?  Or balloon the API for listening for, say, a "@\b[^\b]*\b" in a 
string in a textfield so you only get a message when one exists?  Etc... 
etc...  The Keyboard API would get larger with such an API change and the 
same style would have to be copied into everything that could potentially 
be subscribed to else no filtering in those either except in update (which 
would still call subscriptions/view).  It just seems like a very slippery 
slope to me.  If such an API was added to Keyboard then someone could point 
to it as an example of why it should be added to on a Scroll message, or 
handling input, or etc...  `filters` may be a new callback but it gathers 
all of those needed things in to one place while keeping 
update/subscriptions highly readable, as well as filters being highly 
readable as it only handles one concept, filtering, instead of having 
spaghetti code all over the place to do this testing.  With `filters` my 
code has shrunk in size, a lot of 'if' and 'case's are just gone (not moved 
to filter, a lot are entirely *gone*).  It handles this case, and others 
without starting down the slippery slope of API ballooning.


 

> 2016-08-10 19:38 GMT+02:00 OvermindDL1 <overm...@gmail.com <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 <overm...@gmail.com>:
>>>
>>>> > 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 <falling...@gmail.com>:
>>>>>
>>>>>> 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 <overm...@gmail.com> 
>>>>>> 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 <overm...@gmail.com> 
>>>>>>>> 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 <
>>>>>>>>>> janis.voi...@gmail.com> 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 <
>>>>>>>>>>> janis.voi...@gmail.com>:
>>>>>>>>>>>
>>>>>>>>>>>> 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 elm-discuss...@googlegroups.com.
>>>>>>>>>>> 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 elm-discuss...@googlegroups.com.
>>>>>>>>> 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 elm-discuss...@googlegroups.com.
>>>>>>> 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 elm-discuss...@googlegroups.com.
>>>>>> 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 elm-discuss...@googlegroups.com.
>>>> 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 elm-discuss...@googlegroups.com <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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to