Re: [elm-discuss] Re: Module communication (state machine)

2016-08-08 Thread Mark Hamburg
I like that. I hadn't thought about the option of having the login logic signal 
that it was done by returning a totally different type in the model position. 
Then the state machine can map that result appropriately.

Mark

> On Aug 8, 2016, at 6:43 PM, Ian Mackenzie  wrote:
> 
> I do rather like #2 - it seems to me that you could even have the result of 
> update be either the usual model/command pair or a UserId, i.e. replace both 
> return values, not just the second one. Something like:
> 
> type State
> = Active ( Model, Cmd Msg )
> | Finished UserId
> 
> update : Msg -> Model -> State
> update msg model =
> ...
> 
> which is very explicit - either we're still in the process of logging in, so 
> here is the updated model and some more commands to perform, or the user has 
> finished logged in so you should use the returned user ID to switch to some 
> new state.
> 
>> On Tuesday, 9 August 2016 10:12:26 UTC+10, Mark Hamburg wrote:
>> Here is the case I'm looking at: My SPA can be in one of three state — 
>> probably more before I'm done but three will be sufficient for this 
>> discussion — logging in, active, and logged out. So, here's my model:
>> 
>> type Model
>>   = LoggingIn LoggingIn.Model
>>   | Active Active.Model
>>   | LoggedOut LoggedOut.Model
>> 
>> The message handling has appropriate tag messages and the update function 
>> looks fairly nice by casing on (msg, model). All good so far.
>> 
>> Now, for the question: How best to drive state transitions?
>> 
>> For example, when we finish logging in, we should get back a UserId that we 
>> can hand to Active.init to get an (Active.Model, Cmd Active.Msg). How should 
>> this be reported? The cases I've considered include:
>> 
>> 1. Add an extra Maybe UserId result to LoggingIn.update.
>> 
>> 2. Replace the second result from LoggingIn.update with something that can 
>> be either a Cmd LoggingIn.Msg or a LoggedIn UserId.
>> 
>> 3. Add a loggedInUser : Model -> Maybe UserId function to the LoggingIn 
>> module and test this after doing the update.
>> 
>> Interesting side question: If we do succeed in logging in, is it ever 
>> reasonable to be returning commands (effects) from that update to the 
>> logging in model? The results aren't going to get routed back because that 
>> model state is going away. On the other hand, if we were just sending off 
>> some sort of external effect for which the result didn't matter, then maybe 
>> this could come up.
>> 
>> If the answer to the side question says "yes, it is reasonable to send off 
>> commands as part of login success", then the second option needs a more 
>> complicated type since we can return both a command AND a user id. In that 
>> case, the first case probably wins.
>> 
>> On the other hand, returning triples with what in the general case will be 
>> arbitrary third parameters feels like the sort of coding pattern that decays 
>> into returning quads and quints.
>> 
>> The benefit of the third path is that now one could imagine testing the 
>> logging in module by itself with a view case for when logged in. The state 
>> machine just drives us from this state to the active state.
>> 
>> The downside to the third path is that now every state implementation needs 
>> to include a state for while it is doing what it would ordinarily do and a 
>> state for when it is time to move on and that's more plumbing at those 
>> levels. For example, the Active module would similarly gain an isLoggedOut : 
>> Model -> Bool function and the model within the module would need to handle 
>> the logged out case even though it really has nothing to do in that case,
>> 
>> How would more experienced Elm coders handle this? Is there a sense for best 
>> practice?
>> 
>> My personal inclination is probably to go for the first option even though 
>> it starts to step out onto the slippery slope. I like the second approach 
>> because it feels more rigorous but I think that extra rigor just turns into 
>> extra code in practice. My first implementation today pursued the third 
>> course and I thought it looked nice in my top-level module until I thought 
>> about the fact that it would turn everything below it into a state machine 
>> as well.
>> 
>> Mark
> 
> -- 
> 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.

-- 
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.


[elm-discuss] Re: Module communication (state machine)

2016-08-08 Thread Ian Mackenzie
I do rather like #2 - it seems to me that you could even have the result of 
update be either the usual model/command pair *or* a UserId, i.e. replace 
both return values, not just the second one. Something like:

type State
= Active ( Model, Cmd Msg )
| Finished UserId

update : Msg -> Model -> State
update msg model =
...

which is very explicit - either we're still in the process of logging in, 
so here is the updated model and some more commands to perform, or the user 
has finished logged in so you should use the returned user ID to switch to 
some new state.

On Tuesday, 9 August 2016 10:12:26 UTC+10, Mark Hamburg wrote:
>
> Here is the case I'm looking at: My SPA can be in one of three state — 
> probably more before I'm done but three will be sufficient for this 
> discussion — logging in, active, and logged out. So, here's my model:
>
> type Model
>   = LoggingIn LoggingIn.Model
>   | Active Active.Model
>   | LoggedOut LoggedOut.Model
>
> The message handling has appropriate tag messages and the update function 
> looks fairly nice by casing on (msg, model). All good so far.
>
> Now, for the question: How best to drive state transitions?
>
> For example, when we finish logging in, we should get back a UserId that 
> we can hand to Active.init to get an (Active.Model, Cmd Active.Msg). How 
> should this be reported? The cases I've considered include:
>
> 1. Add an extra Maybe UserId result to LoggingIn.update.
>
> 2. Replace the second result from LoggingIn.update with something that 
> can be either a Cmd LoggingIn.Msg or a LoggedIn UserId.
>
> 3. Add a loggedInUser : Model -> Maybe UserId function to the LoggingIn 
> module and test this after doing the update.
>
> Interesting side question: If we do succeed in logging in, is it ever 
> reasonable to be returning commands (effects) from that update to the 
> logging in model? The results aren't going to get routed back because that 
> model state is going away. On the other hand, if we were just sending off 
> some sort of external effect for which the result didn't matter, then maybe 
> this could come up.
>
> If the answer to the side question says "yes, it is reasonable to send off 
> commands as part of login success", then the second option needs a more 
> complicated type since we can return both a command AND a user id. In that 
> case, the first case probably wins.
>
> On the other hand, returning triples with what in the general case will be 
> arbitrary third parameters feels like the sort of coding pattern that 
> decays into returning quads and quints.
>
> The benefit of the third path is that now one could imagine testing the 
> logging in module by itself with a view case for when logged in. The state 
> machine just drives us from this state to the active state.
>
> The downside to the third path is that now every state implementation 
> needs to include a state for while it is doing what it would ordinarily do 
> and a state for when it is time to move on and that's more plumbing at 
> those levels. For example, the Active module would similarly gain an 
> isLoggedOut 
> : Model -> Bool function and the model within the module would need to 
> handle the logged out case even though it really has nothing to do in that 
> case,
>
> How would more experienced Elm coders handle this? Is there a sense for 
> best practice?
>
> My personal inclination is probably to go for the first option even though 
> it starts to step out onto the slippery slope. I like the second approach 
> because it feels more rigorous but I think that extra rigor just turns into 
> extra code in practice. My first implementation today pursued the third 
> course and I thought it looked nice in my top-level module until I thought 
> about the fact that it would turn everything below it into a state machine 
> as well.
>
> Mark
>
>

-- 
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.


[elm-discuss] Re: Module communication (state machine)

2016-08-08 Thread Max Goldstein
I might need more code to understand what's going on, but I'd do something 
like this:

type Msg = SuccessfulLogin UserId | ActiveCmd Active.Msg | ...

update : Msg -> Model -> (Model, Cmd Msg
update msg model =
  case msg of
SuccessfulLogin userId ->
  let
(activeModel, activeCmd) = Active.init userId
  in
(Active activeModel, Cmd.map ActiveCmd activeCmd)

ActiveCmd activeMsg ->
   -- handle sending the active model its message if present
   

-- 
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.