Можно ли совместить с разложенными последовательностями в 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." И нажмите вкладку много); он может иметь то, что вы хотите.