抽象集合类型

时间:2011-04-20 11:25:22

标签: collections f# language-features

是否有可能编写除了使用seq模块以外它们支持的集合类型的通用函数?

目标是,在添加新的集合函数时不必复制和粘贴。

2 个答案:

答案 0 :(得分:2)

使用集合的通用编程可以像通用编程一样处理:使用泛型。

let f (map_fun : ('T1 -> 'T2) -> 'T1s -> 'T2s) (iter_fun : ('T2 -> unit) -> 'T2s -> unit) (ts : 'T1s) (g : 'T1 -> 'T2) (h : 'T2 -> unit)=
    ts
    |> map_fun g
    |> iter_fun h

type A =
    static member F(ts, g, h) = f (Array.map) (Array.iter) ts g h
    static member F(ts, g, h) = f (List.map) (List.iter) ts g h

有点丑陋和冗长,但这是可能的。我正在使用类和静态成员来利用重载。在您的代码中,您可以只使用A.F并调用正确的专业化。

有关更漂亮的解决方案,请参阅https://stackoverflow.com/questions/979084/what-features-would-you-add-remove-or-change-in-f/987569#987569虽然此功能仅针对核心库启用,但修改编译器以在代码中允许此功能应该不会有问题。这是可能的,因为编译器的源代码是开放的。

答案 1 :(得分:1)

seq<'T>类型是编写适用于F#中任何集合的计算的主要方式。您可以通过以下几种方式使用该类型:

  • 您可以使用Seq模块中的功能(例如Seq.filterSeq.windowed等。)
  • 您可以使用序列理解(例如seq { for x in col -> x * 2 }
  • 您可以使用基础(命令式)IEnumerator<'T>类型,有时需要此类型,例如如果你想实现自己的集合压缩(这是通过调用GetEnumerator
  • 返回的

这是一种相对简单的类型,它只能用于从集合中读取数据。结果,您将始终获得类型为seq<'T>的值,这实际上是一个惰性序列。

F#没有任何转换集合的机制(例如,使用新值将集合C带到集合C的通用函数)或任何创建集合的机制(可在Haskell或Scala中使用)

在大多数实际情况中,我没有发现问题 - 大多数工作都可以使用seq<'T>来完成,当你需要专门的集合(例如性能数组)时,你通常需要一个反正意见略有不同。