Вот версия, портированная с Haskell:
let replicate n x = [for i in 1 .. n -> x]
let sequence ms =
List.fold (fun m' m -> [for x in m do for xs in m' -> (x::xs)]) [[]] ms
let Cpower n l = replicate n l |> sequence
Это работает как подсчет: если вы думаете о l
как о цифрах, то он копирует их на количество мест, которые у вас есть, а затем считает их с помощью sequence
.
Другими словами, все двоичные числа, меньшие 2 ^ 3, могут быть сгенерированы путем репликации [0;1]
3 раза, чтобы получить [[0;1]; [0;1]; [0;1]]
, а затем запустить на них sequence
.
Это можно сделать более ленивым, переключившись на Seq.fold
:
let sequence' ms =
Seq.fold (fun m' m -> seq {for x in m do for xs in m' do yield (x::xs)})
(seq {yield []})
ms
Это дает вам последовательность результатов вместо списка. К сожалению, я не могу сказать, посмотрев на него, лениво ли достаточно : возможно, ему придется сгенерировать весь список в памяти, чтобы начать давать вам первый элемент. Вы должны быть в состоянии выяснить это, пройдя через это в отладчике. (Или вы можете лучше читать лень, чем я.)