我似乎记得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时,它似乎会评估序列中的所有元素,即使它是无限的。
答案 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键);它可能有你想要的东西。