Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to match with decomposed sequences in F#?

Tags:

I seem to remember an older version of F# allowing structural decomposition when matching sequences just like lists. Is there a way to use the list syntax while keeping the sequence lazy? I'm hoping to avoid a lot of calls to Seq.head and Seq.skip 1.

I'm hoping for something like:

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

But this only handles lists and gives a type error when using sequences. When using List.of_seq, it seems to evaluate all the elements in the sequence, even if it is infinite.

like image 225
Ball Avatar asked Nov 17 '09 15:11

Ball


2 Answers

If you use the LazyList type in the PowerPack, it has Active Patterns called LazyList.Nil and LazyList.Cons that are great for this.

The seq/IEnumerable type is not particulaly amenable to pattern matching; I'd highly recommend LazyList for this. (See also 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 
like image 91
Brian Avatar answered Sep 30 '22 21:09

Brian


Seq works fine in active patterns! Unless I'm doing something horrible here...

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 
like image 34
Dan Fitch Avatar answered Sep 30 '22 19:09

Dan Fitch