如何在 Elm 的给定列表中获取随机元素?

How to get a random element in a given List in Elm?

我正在制作一款滑动益智游戏:

从这个初始位置开始,我想洗牌,比如说 100 步。

我希望每次都以不同的方式洗牌。

这可能意味着我需要每次用不同的号码呼叫Random.initialSeed,这意味着我需要使用类似当前时间的东西。

很遗憾,我找不到如何获取当前时间。

在每个给定的状态下,我都有一个可能的动作列表。比如上面的初始位置:[MoveRight, MoveDown]

所以,基本上,我的问题是:如何在给定列表中获取随机元素?

share-elm 示例将不胜感激。

粗略的答案(现在不在编译器附近):

如果您想根据当前时间改变种子,请将 Time.every 添加到您的信号图中:

http://package.elm-lang.org/packages/elm-lang/core/2.1.0/Time#every

在你的模型中保留最后一次看到的时间戳,然后,当你需要洗牌时,用它来为你的随机数播种。生成一个[1,长度列表]范围内的整数,然后选择该索引的元素。

希望这是一个足够的提示,如果不够请大声说出来,我会在有机会时详细说明。

这是对 pdamoc 答案的修订。它更紧密地遵循 The Elm Architecture,但更重要的是,它保存了从印刷机到印刷机的随机种子。如果您继续使用初始种子,您将不会获得随机性。我在另一个版本中只得到偶数或奇数(得到偶数,刷新,得到赔率)。在您的程序中只调用一次 Random.initialSeed 很重要,通常是在初始模型的定义中。

还有a library(我写的)处理数组的随机操作。

import Html exposing (..) 
import Html.Events exposing (onClick) 
import Random exposing (initialSeed, int, generate, Seed)

type alias Model = 
  { list : List Int , currentElement : Maybe Int, seed : Seed}

init : Model 
init = {list = [1..10], currentElement = Nothing, seed = initialSeed 42 } 

type Action = NoOp | Click

actions : Signal.Mailbox Action
actions = Signal.mailbox NoOp

update : Action -> Model -> Model
update action model =
  case action of
    NoOp -> model
    Click ->
      let gen = Random.int 0 (List.length model.list - 1)
          -- since we know the list is constant we don't have to
          -- redefine the generator every time, but we will anyway
          (i, seed) = Random.generate gen model.seed
          elem = List.drop i model.list |> List.head
      in {model| currentElement <- elem, seed <- seed}

model : Signal Model
model = Signal.foldp update init actions.signal

view : Signal.Address Action -> Model -> Html
view address model = 
  let 
    current = model.currentElement
              |> Maybe.map toString
              |> Maybe.withDefault "NONE"
  in 
    div [] 
      [ text  <| toString model.list
      , br [] []
      , text  <| "Current Element: " ++ current
      , br [] []
      , button [onClick address Click ] [text "Click for Random Element"]
      ]

main = Signal.map (view actions.address) model

我创建了 Elm 的 StartApp 示例的一个变体,其中包括每个事件的时间,仅当事件发生时。

https://gist.github.com/z5h/41ca436679591b6c3e51

您的更新函数现在看起来像:

update : action -> Time -> model -> (model, Effects action)