21

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

4

3 回答 3

27

如果您在 PowerPack 中使用 LazyList 类型,它具有称为 LazyList.Nil 和 LazyList.Cons 的 Active Patterns 非常适合此操作。

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
于 2009-11-17T15:29:33.373 回答
11

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
于 2009-11-18T16:40:58.050 回答
1

记住 seq 也有 map reduce 函数,所以你可能经常只能使用这些函数。在示例中,您的函数等效于“Seq.isEmpty”。您可能会尝试启动 fsi 并只运行制表符完成选项(输入“Seq.”并多次单击制表符);它可能有你想要的。

于 2010-06-11T19:48:30.900 回答