Great post! So after this exercise, do you think making Model into a pure Custom Type is the way to go for larger projects? Or is this only suitable for small demos? (As opposed to the "traditional" Elm Model, which is a record made up of many types and custom types.)
I'm a software developer based in Newcastle Upon Tyne, England. I've got a wide range of experience in companies of varying sizes and cultures, and in roles of varying degrees of responsibility.
I'm by no means an expert in Elm, so it's difficult for me to say for certain (although I'm currently working on a larger Elm application and I'm sure I'll come out of that with more thoughts!), but my current thought on this is that yes, I do prefer the idea of the Model being a Custom Type as opposed to a record. The main thing I kept coming up against when having the model be a record was that it seemed like every separate view ended up having information (or at least theoretical access to information) that it just didn't need - it could very well be that I wasn't organising my models very well, but since making this change in my own code things have felt easier to deal with and reason about.
Again, my thoughts on this in future might change, but as of right now (which is after all when you're asking :D ) I think that this approach is helpful for reasoning about the application itself - if your Model is always describing the state of your application, then it feels likely that this will make life easier for anyone maintaining your application in the future - something I think we should all be careful to consider.
I'm a software developer based in Newcastle Upon Tyne, England. I've got a wide range of experience in companies of varying sizes and cultures, and in roles of varying degrees of responsibility.
Ah I think my wording has probably confused matters - Model is the custom type, DisplayingRoom and Failure are values that custom type can have. (These are known as type variants)
DoorState and AlarmState are also custom types.
This might help clarify things a little:
Consider Bool - that is a type that can have a value of either True or False, and would be represented (and I imagine probably actually is represented in the source code!) as:
Ooohh yes, that makes perfect sense! A custom type can have any... custom... values you make up, they don't have to be defined separately anywhere else. I get it now. My mental block was that I was still thinking of the Model type as a record, just because it was named Model. LOL.
I guess I'm starting to see why "custom types" is a better name than "union types" (what they used to be in 0.18). Thanks for the update to 0.19!
I'm a software developer based in Newcastle Upon Tyne, England. I've got a wide range of experience in companies of varying sizes and cultures, and in roles of varying degrees of responsibility.
Glad that helped! I can totally see how that caused confusion.
And yeah, I think the change of naming convention from union to custom is a big positive. Custom type is a phrase that can be easily understood without even having any real understanding of the language at all! :)
I'm a software developer based in Newcastle Upon Tyne, England. I've got a wide range of experience in companies of varying sizes and cultures, and in roles of varying degrees of responsibility.
Slight update: After adding navigation into another application, which meant needing to add a navigation key, I've ended up re-evaluating this at the moment. Although all I've done is added any globally-available info to the model, and kept the state the way I described earlier:
And it's still the state that drives the UI itself:
-- VIEWview:Model->DocumentMsgviewmodel=casemodel.stateofLoading->{title="Some app",body=[loadingView]}ViewSignUpdata->letsignUpView=Html.map(\x->SignUpMsgx)<|SignUp.viewdatain{title="Sign up to Some app",body=[signUpView]}ViewLogindata->letloginView=Html.map(\x->LoginMsgx)<|Login.viewdatain{title="Log in to Some app",body=[loginView]}ViewPasswordResetdata->letforgottenPasswordView=Html.map(\x->PasswordResetMsgx)<|PasswordReset.viewdatain{title="Request a password reset",body=[forgottenPasswordView]}
I do like this better. Somehow it feels a little "forced" to make the model as one giant custom type. With this type of edit, you can still model your door/alarm states elegantly and completely with a big custom type, and get all the benefits of that. But other stuff in the model (like navigation key or login status) that doesn't have anything to do with the door state can live separately, as a different piece of the model record.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Great post! So after this exercise, do you think making
Model
into a pure Custom Type is the way to go for larger projects? Or is this only suitable for small demos? (As opposed to the "traditional" ElmModel
, which is a record made up of many types and custom types.)Thanks! <3
I'm by no means an expert in Elm, so it's difficult for me to say for certain (although I'm currently working on a larger Elm application and I'm sure I'll come out of that with more thoughts!), but my current thought on this is that yes, I do prefer the idea of the
Model
being a Custom Type as opposed to a record. The main thing I kept coming up against when having the model be a record was that it seemed like every separate view ended up having information (or at least theoretical access to information) that it just didn't need - it could very well be that I wasn't organising my models very well, but since making this change in my own code things have felt easier to deal with and reason about.Again, my thoughts on this in future might change, but as of right now (which is after all when you're asking :D ) I think that this approach is helpful for reasoning about the application itself - if your Model is always describing the state of your application, then it feels likely that this will make life easier for anyone maintaining your application in the future - something I think we should all be careful to consider.
Also, looking at it more carefully... how is the top-level
DisplayingRoom
type defined? I'm sure that's a ridiculously basic question...Ah I think my wording has probably confused matters -
Model
is the custom type,DisplayingRoom
andFailure
are values that custom type can have. (These are known astype variants
)DoorState
andAlarmState
are also custom types.This might help clarify things a little:
Consider
Bool
- that is atype
that can have a value of eitherTrue
orFalse
, and would be represented (and I imagine probably actually is represented in the source code!) as:Does that answer your question? :)
Ooohh yes, that makes perfect sense! A custom type can have any... custom... values you make up, they don't have to be defined separately anywhere else. I get it now. My mental block was that I was still thinking of the
Model
type as a record, just because it was named Model. LOL.I guess I'm starting to see why "custom types" is a better name than "union types" (what they used to be in 0.18). Thanks for the update to 0.19!
Glad that helped! I can totally see how that caused confusion.
And yeah, I think the change of naming convention from
union
tocustom
is a big positive.Custom type
is a phrase that can be easily understood without even having any real understanding of the language at all! :)Slight update: After adding navigation into another application, which meant needing to add a navigation key, I've ended up re-evaluating this at the moment. Although all I've done is added any globally-available info to the
model
, and kept thestate
the way I described earlier:And it's still the
state
that drives the UI itself:I do like this better. Somehow it feels a little "forced" to make the model as one giant custom type. With this type of edit, you can still model your door/alarm states elegantly and completely with a big custom type, and get all the benefits of that. But other stuff in the model (like navigation key or login status) that doesn't have anything to do with the door state can live separately, as a different piece of the model record.