Можно ли сопоставить разложенные последовательности в 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 кажется, что оцениваются все элементы в последовательности, даже если она бесконечна.


person Ball    schedule 17.11.2009    source источник


Ответы (3)


Если вы используете тип 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
person Brian    schedule 17.11.2009
comment
ссылка здесь для тех, кто (как я) не знал, что такое блок питания: fsharppowerpack.codeplex.com - person gatoatigrado; 11.06.2010
comment
LazyList теперь является частью FSharpx.Collections: fsprojects.github. io/FSharpx.Collections/reference/ - person DharmaTurtle; 09.11.2019

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, поэтому общая аннотация становится дурацкой...

person Dan Fitch    schedule 18.11.2009
comment
Один трюк для случаев, когда вам нужна одинарная одинарная кавычка: добавьте еще одну одинарную кавычку в комментарий в конце строки: // ' - person harms; 18.11.2009
comment
Это ловкий трюк, но несколько надежных источников указывают на то, что это не очень хороший шаблон, поскольку оценка последовательности равна O (n ^ 2): stackoverflow.com/questions/1306140/ - person Juliet; 18.11.2009
comment
Верно, но пример вопрошающего не рекурсивен. Это, очевидно, не подходит для рекурсии вниз по последовательности, но если вы просто хотите сопоставить шаблон на голове или что-то в этом роде... - person Dan Fitch; 19.11.2009

Помните, что в seq также есть функции уменьшения карты, так что часто вам может сойти с рук только их. В примере ваша функция эквивалентна «Seq.isEmpty». Вы можете попробовать запустить fsi и просто просмотреть параметры завершения вкладок (введите «Seq.» и много раз нажимайте tab); в нем может быть то, что вы хотите.

person gatoatigrado    schedule 11.06.2010