'What is the minimum code required to produce random numbers in Elm?

I just want to see a random number. So here's an example straight out of the docs for the Random library. I expect Random.generate to accept a generator and a seed and return a tuple containing a random value and a new seed, as in:

generate : Generator a -> Seed -> (a, Seed)

-- Main.elm

import Random

seed0 = Random.initialSeed 31415
randomNumber = Random.generate (Random.int 0 10) seed0
main = 
  -- print result of randomNumber here

The compiler errors show two type mismatches:

-- TYPE MISMATCH ---------------------------------------------------- -----------

The 2nd argument to function `generate` is causing a mismatch.

5|        Random.generate (Random.int 0 10) seed0
                                        ^^^^^
Function `generate` is expecting the 2nd argument to be:

    Random.Generator a

But it is:

    Random.Seed


The 1st argument to function `generate` is causing a mismatch.

5|        Random.generate (Random.int 0 10) seed0
                       ^^^^^^^^^^^^^^^
Function `generate` is expecting the 1st argument to be:

    a -> b

But it is:

    Random.Generator Int

What am I missing here?



Solution 1:[1]

The version of the docs you refer to is Core 1.0.0, which is old. Current version of Core is 4.0.5. (docs for Random here)

The function with the signature you are looking for is now named step:

step : Generator a -> Seed -> (a, Seed)

So your refactored code would look something like this:

import Html exposing (text)
import Random

seed0 = Random.initialSeed 31415
(randomNumber, nextSeed) = Random.step (Random.int 0 10) seed0

main =
  text <| toString randomNumber

Solution 2:[2]

Here is the shortest example I can think of. Because it is giving a constant seed, it will return same boolean.

If you need random number get produced at runtime, then you have to use Random.generate which produces Cmd so that elm runtime can get the randomness. In this case, some form of Platform.Program is needed because it is the only way to run Cmd.

import Html exposing (text)
import Random exposing (..)

main =
  text <| toString <| Tuple.first <| step bool (initialSeed 1)

Solution 3:[3]

Elm 2022 (v0.19) answer:

Here's an absolute minimal example for generating a number between 0 and 1000 in Elm 0.19.1, and a runnable Ellie, which depends on elm/random. You wouldn't usually have all the () littered throughout, and instead you'd have Msg and Model, but in the interest of minimizing code:

module Main exposing (main)

import Browser
import Html
import Random


view : () -> Html.Html ()
view model =
    let
        -- this generates the rng number
        generator =
            Random.int 0 1000

        -- used to seed the generator
        seed =
            Random.initialSeed 12345

        -- Random.step returns the generated value, and a new seed.
        -- Usually you store the newSeed on your model so you don't always generate the same value
        ( value, newSeed ) =
            Random.step
                generator
                seed
    in
    Html.text <| String.fromInt value


main : Program () () ()
main =
    Browser.sandbox
        { init = ()
        , view = view
        , update = \msg model -> model
        }

Other best practices include storing some global seed on the model:

type alias Model = { globalSeed : Random.Seed }

and then using it and updating the one on the model after:

update : Msg -> Model -> (Model, Cmd.none)
update msg model =
    case msg of
       GenerateValue ->
          let
             (newValue, newSeed) =
               Random.step (Random.int 0 1000) model.globalSeed

             _ =
               Debug.log "generated a new value" newValue

          in
          ( {model | globalSeed = newSeed}, Cmd.none)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 wintvelt
Solution 2 rofrol
Solution 3