I'm trying to wrap my head around Elm. I have experience in Haskell, and a bit of Erlang.
I want to complete the following exercise:
- User is shown a login form
- On submit, the frontend makes a request to
localhost/authto try and receive an auth token. - On success, the homepage is shown, which fetches some data.
- On failure, the login screen displays an error.
This is quite basic, but hopefully complex enough to model the behaviour of a real webapp.
My first problem is with the Model. I only need the data if the client is authenticated. Should I wrap this in something similar to a Maybe monad?
type Model
= NoAuth String String
| AuthFetching
| AuthFailed err
| AuthSuccess String
And then the login screen can display a spinner, and error, or redirect to a new page.
This feels like it ties the rest of the applications state to the authentication state. Although is is "correct", it feels wrong to have the whole model be a (variant type?) with only one record.
It "feels" more correct to have the model like so:
type FetchStatus
= Loading
| Success val
| Err err
type Model =
{ token : RequestStatus String
, data : List number
}
But whenever you update the model, you now need to check if token is still present - i.e. pattern match within the record. In the first example, you only needed to pattern match on the whole model, which is a bit simpler.
And to hold the login form state, I'd need to add extra fields:
type Model =
{ token : RequestStatus String
, data : List number
, username : String
, password : String
}
Which feels incorrect because the password should not be held in memory after login. I'd hold these in records, but I cannot use records in custom type declarations.
All in all, I'm a bit confused. Can someone please shed some light on the most "correct", idiomatic way to do this?