Можно ли совместить с разложенными последовательностями в F #?
Кажется, я помню более старую версию F #, позволяющую структурную декомпозицию при сопоставлении последовательностей, подобных спискам. Есть ли способ использовать синтаксис списка, сохраняя последовательность ленивым? Я надеюсь избежать много вызовов Seq.head и Seq.skip 1.
Я надеюсь на что-то вроде:
let decomposable (xs:seq<'a>) =
match xs with
| h :: t -> true
| _ -> false
seq{ 1..100 } |> decomposable
Но это только обрабатывает списки и дает ошибку типа при использовании последовательностей. При использовании List.of_seq он, кажется, оценивает все элементы в последовательности, даже если он бесконечен.
Ответы
Ответ 1
Если вы используете тип LazyList в PowerPack, у него есть активные шаблоны, называемые LazyList.Nil и LazyList.Cons, которые отлично подходят для этого.
Тип seq/IEnumerable не является особенно подходящим для сопоставления шаблонов; Я очень рекомендую LazyList для этого. (См. Также Почему использование последовательности происходит намного медленнее, чем использование списка в этом примере.)
let s = seq { 1..100 }
let ll = LazyList.ofSeq s
match ll with
| LazyList.Nil -> printfn "empty"
| LazyList.Cons(h,t) -> printfn "head: %d" h
Ответ 2
Seq отлично работает в активных шаблонах! Если я не сделаю здесь что-то ужасное...
let (|SeqEmpty|SeqCons|) (xs: 'a seq) = //'
if Seq.isEmpty xs then SeqEmpty
else SeqCons(Seq.head xs, Seq.skip 1 xs)
// Stupid example usage
let a = [1; 2; 3]
let f = function
| SeqEmpty -> 0
| SeqCons(x, rest) -> x
let result = f a
Я не знаю, как получить выделение кода StackOverflow в режиме F #, я думаю, что здесь используется OCaml, поэтому общая аннотация становится неаккуратной...
Ответ 3
Помните, что у seq есть функции уменьшения карты, поэтому вы часто можете уйти только от них. В примере ваша функция эквивалентна "Seq.isEmpty". Вы можете попробовать запустить fsi и просто запустить параметры завершения вкладки (введите "Seq." И нажмите вкладку много); он может иметь то, что вы хотите.