I cannot seem to figure out what constitutes an acceptable Cmd in the context of update: Msg -> Model -> (Model, Cmd msg). For instance if I have defined a function myFunc : Html.msg I can’t seem to do
As presented here, myfunc returns Html msg, but the return value from update should be a Cmd msg. They are different types and are not interchangable.
Html msg is often used for views. Is there some confusion here?
Also, Elm tries hard to produce useful compiler error messages. It’s always worth copying the error you get into your posts as it may help others help you understand what the compiler is telling you so you can work it out yourself in future.
I think I know the conceptual problem you are having. You wouldn’t really ever return an Html.msg from a command. You just update the model, and the views will automatically update.
I have read through the guide but I guess it’s not clear to me what is a valid Cmd. For instance, in the guide Random.generate is considered a valid Cmd. Is this because its return type is Cmd msg? If so, how does one define a proper Cmd? Does it always have to return Cmd.none at some point?
First, Cmd doesn’t mean anything on it’s own. It’s always a “command of something”. In the case randomness,
generate : (a -> msg) -> Generator a -> Cmd msg
So, second, Random.generate is not a command (of anything), but a function that returns a command. The msg type variable can be any type when talking about Random.generate in general. However, any time you actually call Random.generate, the msg gets filled in with a specific type. The random generator will generate a thing of a specific type, and the mapping function you provide (as the first argument) must accept that type. Whatever the mapping function outputs is the “of something” in “command of something”. The way it actually “does work” is hidden from you (but in this case, it gets the current time – an effect – and then uses that to seed a PRNG).
You define a proper command something like this:
type Msg = DiceRoll Int | ...
rollDie : Random.Generator Int
rollDie = Random.int 1 6
myCmd : Cmd Msg
myCmd = Random.generate DiceRoll rollDie
Regarding Cmd.none, that’s a misconception. Cmd.none doesn’t do anything, hence the type variable can be whatever it needs to be. There’s a pattern here:
x : List a implies x == []
y : Maybe b implies y == Nothing
z : Html msg implies z produces no messages (essentially, z has no bound event handlers)
c : Cmd msg implies c is Cmd.none, it produces no effects
(Note that you can use any lowercase string you want for a type variable, but msg and Msg are different - Msg is a specific type.) The pattern is that when you have a container whose elements are of any type, that container is actually empty.
Thank you, that’s very helpful. What about the case where your function does not utilize a function that already returns a Cmd Msg? So Random.generate is going to return a Cmd Msg but how do I create a function that returns a valid Cmd Msg de novo?
If you don’t need to do any “effects” – pseudorandomness, send an HTTP request, get the current time, send a value out a port – then use Cmd.none. The type Cmd msg will be unified with Cmd Msg.
Yes, that’s correct. In a simple app, you use commands infrequently if at all. Rendering is done separately (render : Model -> Html Msg), and any events the HTML generates are passed back into update without any extra work on your part.