Звонок 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
Если мы концептуально упростить понятие Seed к 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
исправляет выход и возвращает его в область предсказуемости.
, потому что мы можем предварять одно значение в список, и мы можем только добавить список в список. Так что это всего лишь вопрос реализации http://package.elm-lang.org/packages/elm-lang/core/latest/List – rofrol