Question about Random.generate and its first argument


I’ve just done the chapter about generating random numbers from the official elm guide and there is something that I can’t understand.

In the code I defined message type:

type Msg =
| NewFace Int

and then in the update function when RollDice event is received I call the Random.generate in following way:

Random.generate NewFace ( 1 6)

and that is the bit that confuses in: in docs for Random packages I can read that Random.generate have following signature:

random: (a -> msg) -> Generator a -> Cmd msg

How it’s possible that NewFace “fits” into (a -> msg)?

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
1 Like

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!


thank you! That explanation really make things clear!

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.