Random.generate is considered a valid Cmd.
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.