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

Bal*_*all 16 f# list sequence pattern-matching lazy-evaluation

我似乎记得F#的旧版本允许在匹配序列时进行结构分解,就像列表一样.有没有办法在保持序列延迟的同时使用列表语法?我希望避免大量调用Seq.head和Seq.skip 1.

我希望有类似的东西:

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

但这仅处理列表并在使用序列时给出类型错误.当使用List.of_seq时,它似乎会评估序列中的所有元素,即使它是无限的.

Bri*_*ian 23

如果你在PowerPack中使用LazyList类型,它有一个名为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
Run Code Online (Sandbox Code Playgroud)

  • 链接到这里的人(像我一样)不知道电源组是什么:http://fsharppowerpack.codeplex.com/ (5认同)

Dan*_*tch 9

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
Run Code Online (Sandbox Code Playgroud)

我不知道如何将StackOverflow的代码突出显示为F#模式,我认为它在这里使用OCaml所以通用注释很古怪......

  • 它是一个巧妙的技巧,但不止一个可靠的来源表明,自评估序列以来它不是一个好的模式是O(n ^ 2):http://stackoverflow.com/questions/1306140/f-why-is-using-一个序列那么多-慢于使用-A-列表在此结果示例/ 1306267#1306267 (7认同)
  • 您需要单个引号的实例的一个技巧:在行末的注释中添加另一个单引号://' (3认同)