是否有可能与F#中的分解序列匹配?

时间:2009-11-17 15:17:36

标签: list f# pattern-matching sequence lazy-evaluation

我似乎记得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时,它似乎会评估序列中的所有元素,即使它是无限的。

3 个答案:

答案 0 :(得分:22)

如果你在PowerPack中使用LazyList类型,它有一个名为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

答案 1 :(得分:8)

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所以通用注释很古怪......

答案 2 :(得分:0)

请记住seq也有map reduce函数,所以你可能经常只能使用它们。在该示例中,您的函数等效于“Seq.isEmpty”。您可以尝试启动fsi并只运行选项卡完成选项(输入“Seq。”并点击Tab键);它可能有你想要的东西。