NewFace is actually a function of type Int -> Msg, which is a valid argument for generate that accepts the more general a -> msg, provided that you also pass it a Generator Int, and it will then return a Cmd Msg.
So the type inferred at compilation for this generate use will be:
generate: (Int -> Msg) -> Generator Int -> Cmd Msg
elaborating on @dmy’s answer, defining a custom type generates functions to construct values of their type. Sometimes you’ll see the cases of a custom type being called “constructors”. This is why! So if I had this type:
type Msg =
Hello String
Then I can both construct it: Hello "matekm"
and match on it:
case msg of
Hello whom ->
Html.text ("Hello, " ++ whom)
This holds for custom types with multiple arguments. That means that:
type Demonstration
= NoArguments -- has the signature `Demonstration`
| OneArgument String -- has the signature `String -> Demonstration`
| TwoArguments Int String -- has the signature `Int -> String -> Demonstration`
So in your case:
type Msg
= RollDice -- has the signature `Msg`
| NewFace Int -- has the signature `Int -> Msg`
And since Int -> Msg matches a -> msg, the call to Random typechecks!