2009-11-17 6 views
15

Кажется, я помню более старую версию F #, позволяющую структурную декомпозицию при сопоставлении последовательностей, подобных спискам. Есть ли способ использовать синтаксис списка, сохраняя последовательность ленивым? Я надеюсь, чтобы избежать много звонков Seq.head и Seq.skip 1.Можно ли совместить с разложенными последовательностями в F #?

Я надеюсь, что-то вроде:

let decomposable (xs:seq<'a>) = 
    match xs with 
    | h :: t -> true 
    | _ -> false 
seq{ 1..100 } |> decomposable 

Но это обрабатывает только списки и дает ошибку типа, когда используя последовательности. При использовании List.of_seq он, кажется, оценивает все элементы в последовательности, даже если он бесконечен.

ответ

21

Если вы используете тип LazyList в PowerPack, у него есть активные шаблоны LazyList.Nil и LazyList.Cons, которые отлично подходят для этого.

Тип seq/IEnumerable не является особенно подходящим для соответствия шаблону; Я очень рекомендую LazyList для этого. (См. Также Why is using a sequence so much slower than using a list in this example.)

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 
+5

ссылка здесь для тех, кто (как я) не знал, что такое блок питания: http://fsharppowerpack.codeplex.com/ – gatoatigrado

7

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

Один трюк для случаев, когда вам нужна одиночная кавычка: цитата в комментарии в конце строки: // ' – harms

+7

Его опрятный трюк, но более одного надежного источника указывает, что его не очень хороший шаблон, так как оценка последовательности - это O (n^2): http: // stackoverflow .com/questions/1306140/f-why-is-use-a-sequence-so-much-slower-than-use-a-list-in-this-example/1306267 # 1306267 – Juliet

+1

Верно, но пример опроса не рекурсивный. Это явно не подходит для повторения последовательности, но если вы просто хотите сопоставить шаблон по голове или чему-то еще ... –

0

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