是否有更通用的方法在F#中对集合进行迭代,过滤和应用操作?

Geo*_*Geo 1 f#

我们来看看这段代码:

open System
open System.IO

let lines = seq {
  use sr = new StreamReader(@"d:\a.h")
  while not sr.EndOfStream do yield sr.ReadLine()
}

lines |> Seq.iter Console.WriteLine
Console.ReadLine()
Run Code Online (Sandbox Code Playgroud)

在这里,我正在阅读a中的所有行seq,并且我正在使用它Seq.iter.如果我有一个我将使用的列表List.iter,如果我有一个数组,我将使用Array.iter.是不是我可以使用更通用的遍历功能,而不是必须跟踪我有什么样的集合?例如,在Scala中,我只是调用a foreach,无论我使用的是List,Array还是Seq,它都能正常工作.

我做错了吗?

Gen*_*ski 5

根据您的具体情况,您可能需要或不需要跟踪您要处理的收集类型.

如果对项目进行简单的迭代,则没有什么可能阻止您Seq.iter在F#中使用列表或数组:它将在数组和列表上工作,因为它们也是序列,或者IEnumerable从.NET的角度来看.Array.iter在数组上使用或List.iter在列表上使用将简单地基于每种类型的集合的特定属性提供更有效的遍历实现.由于Seq.iter的签名Seq.iter : ('T -> unit) -> seq<'T> -> unit显示您'T在遍历后不关心您的类型.

在其他情况下,如果您关心进一步的组合,您可能需要考虑输入和输出参数的类型并使用专门的函数.例如,如果您需要过滤列表并继续使用结果,那么

List.filter : ('T -> bool) -> 'T list -> 'T list将保留底层集合的类型完整,但Seq.filter : ('T -> bool) -> seq<'T> -> seq<'T>应用于列表将返回序列,而不是列表:

let alist = [1;2;3;4] |> List.filter (fun x -> x%2 = 0) // alist is still a list
let aseq = [1;2;3;4] |> Seq.filter (fun x -> x%2 = 0) // aseq is not a list anymore
Run Code Online (Sandbox Code Playgroud)