【问题标题】:Elm random list implementationElm 随机列表实现
【发布时间】:2016-05-02 19:55:01
【问题描述】:

Elm 标准库提供的 a function to generate random lists 可以正常工作。 通过查看its implementation,我们可以看到该列表是以函数样式构造的,即从结尾到开头。当生成足够多的元素时,返回反向列表:

if n < 1 then
    (List.reverse list, seed)

我想知道为什么我们需要颠倒这个列表?是否需要保证“正确”的随机性?

【问题讨论】:

标签: list random elm


【解决方案1】:

List.reverse 调用实际上将列表按生成的顺序放回原处。

这里是相关函数的代码:

list : Int -> Generator a -> Generator (List a)
list n (Generator generate) =
  Generator <| \seed ->
    listHelp [] n generate seed

listHelp : List a -> Int -> (Seed -> (a,Seed)) -> Seed -> (List a, Seed)
listHelp list n generate seed =
  if n < 1 then
    (List.reverse list, seed)
  else
    let
      (value, newSeed) =
        generate seed
    in
      listHelp (value :: list) (n-1) generate newSeed

如果我们在概念上将种子的概念简化为 Int,并假设我们有一个返回 (seed, seed + 1) 的生成器,那么如果我们的初始种子是 1(生成5 个元素的列表):

listHelp [] 5 myGen 1 -- initial state
listHelp [1] 4 myGen 2
listHelp [2,1] 3 myGen 3
listHelp [3,2,1] 2 myGen 4
listHelp [4,3,2,1] 1 myGen 5
listHelp [5,4,3,2,1] 0 myGen 6

然后将最终输出列表反转为您提供[1,2,3,4,5]

最终排序对函数的整体随机性没有任何影响,但如果您要运行具有相同种子但请求不同列表大小的多个列表,它确实会为您提供可预测的结果。

考虑列表是否在最后一步没有反转(假设initialSeed1)。

List.head (list 5 (myGen initialSeed)) == Just 5
List.head (list 4 (myGen initialSeed)) == Just 4

由于所有这些伪随机性都需要 Seed 作为输入,因此以可预测的方式推理事物更有意义,而不是引入会使 list 不可预测的任意重新排序。 List.reverse 修复输出并将其放回可预测的领域。

【讨论】:

    【解决方案2】:

    可能是因为大多数随机生成器并不是真正随机的。如果你用相同的种子开始它们,你会得到相同的序列。如果您依赖这个事实进行测试,那么让序列以相反的顺序返回可能会破坏您的测试。

    这是假设大多数程序员期望生成的序列是按列表顺序排列的,即第一个项目将是第一个生成的。我认为这是一个可能的假设。因此,在最后反转列表是值得的,这样 api 就不那么令人惊讶了。

    【讨论】:

      【解决方案3】:

      因为我们可以将单个值添加到列表中,而我们只能将列表添加到列表中。我们可以

      append list [value]
      

      然后我们就不必反转它了

      http://package.elm-lang.org/packages/elm-lang/core/latest/List

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-16
        • 2020-09-19
        • 2021-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-30
        • 1970-01-01
        相关资源
        最近更新 更多