Ваш seqCombinations
почти верен, но вы не перевели его из списков в последовательности должным образом. Эквивалент [[]]
- это не Seq.empty
, а Seq.singleton Seq.empty
:
let seqCombinations xs =
Seq.fold (fun acc x ->
Seq.collect (fun ys ->
seq { yield ys
yield seq { yield x
yield! ys} }) acc) (Seq.singleton Seq.empty) xs
Код выше работает для конечных последовательностей. Но для бесконечных это не работает, потому что сначала он пытается достичь конца, чего, очевидно, никогда не делает для бесконечных последовательностей.
Если вам нужна функция, которая будет работать с бесконечными последовательностями, мне удалось найти два пути, но ни один из них не особенно хорош. Один из них использует изменяемое состояние:
let seqCombinations xs =
let combs = ref [[]]
seq {
yield! !combs
for x in xs do
let added = List.map (fun ys -> x::ys) !combs
yield! added
combs := !combs @ added
}
Другой вопрос касается подробностей seq<T>
:
open System.Collections.Generic
let seqCombinations (xs : seq<_>) =
let rec combs acc (e : IEnumerator<_>) =
seq {
if (e.MoveNext()) then
let added = List.map (fun ys -> (e.Current)::ys) acc
yield! added
yield! combs (acc @ added) e }
use enumerator = xs.GetEnumerator()
seq {
yield []
yield! combs [[]] enumerator
}
Я думаю, что было бы намного проще, если бы вы могли рассматривать бесконечные последовательности как голову и хвост, как конечные списки в F # или любую последовательность в Haskell. Но вполне возможно, что есть хороший способ выразить это на F #, а я просто не нашел его.