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]。
最终排序对函数的整体随机性没有任何影响,但如果您要运行具有相同种子但请求不同列表大小的多个列表,它确实会为您提供可预测的结果。
考虑列表是否在最后一步没有反转(假设initialSeed 是1)。
List.head (list 5 (myGen initialSeed)) == Just 5
List.head (list 4 (myGen initialSeed)) == Just 4
由于所有这些伪随机性都需要 Seed 作为输入,因此以可预测的方式推理事物更有意义,而不是引入会使 list 不可预测的任意重新排序。 List.reverse 修复输出并将其放回可预测的领域。