在 Elm 中生成随机数所需的最少代码是多少?

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

我只想看一个随机数。所以这里是 Random 库的 an example straight out of the docs。我希望 Random.generate 接受生成器和种子以及 return 包含随机值和新种子的元组,如:

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

编译器错误显示两种类型不匹配:

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

我在这里错过了什么?

这是我能想到的最短的例子。 因为它给出了一个常量种子,所以它将 return 相同的布尔值。

如果您需要在运行时间产生随机数,那么您 必须使用 Random.generate 产生 Cmd 这样 elm 运行time 就可以获得随机性。 在这种情况下,某种形式的 Platform.Program 是必需的,因为它是 运行 Cmd.

的唯一途径
import Html exposing (text)
import Random exposing (..)

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

您参考的文档版本是Core 1.0.0,比较旧。当前的 Core 版本是 4.0.5。 (docs for Random here)

带有您要查找的签名的函数现在命名为 step:

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

所以你的重构代码看起来像这样:

import Html exposing (text)
import Random

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

main =
  text <| toString randomNumber

Elm 2022 (v0.19) 答案:

这是在 Elm 0.19.1 和 a runnable Ellie, which depends on elm/random 中生成 0 到 1000 之间的数字的绝对最小示例。你通常不会把所有的 () 都乱七八糟,而是 MsgModel,但为了最小化代码:

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
        }

其他最佳实践包括在模型上存储一些全局种子:

type alias Model = { globalSeed : Random.Seed }

然后使用它并在之后更新模型上的那个:

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)