对集合类型进行抽象

发布于 2024-11-03 01:36:20 字数 77 浏览 1 评论 0原文

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

目标是在添加新的集合功能时不必诉诸复制和粘贴。

Is there a possibility of writing functions which are generic in respect to collection types they support other than using the seq module?

The goal is, not having to resort to copy and paste when adding new collection functions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

莫言歌 2024-11-10 01:36:20

使用集合进行泛型编程的处理方式与一般进行泛型编程的方式相同:使用泛型。

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

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

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

Generic programming with collections can be handled the same way generic programming is done in general: Using generics.

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 bit ugly and verbose, but it's possible. I'm using a class and static members to take advantage of overloading. In your code, you can just use A.F and the correct specialization will be called.

For a prettier solution, see https://stackoverflow.com/questions/979084/what-features-would-you-add-remove-or-change-in-f/987569#987569 Although this feature is enabled only for the core library, it should not be a problem to modify the compiler to allow it in your code. That's possible because the source code of the compiler is open.

壹場煙雨 2024-11-10 01:36:20

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

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

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

F# 没有任何转换集合的机制(例如将集合 C 转换为具有新值的集合 C 的通用函数)或任何创建集合的机制(Haskell 中提供)或斯卡拉)。

在大多数实际情况下,我没有发现问题 - 大部分工作可以使用 seq<'T> 完成,并且当您需要专门的集合(例如用于性能的数组)时,无论如何,您通常需要稍微不同的实现。

The seq<'T> type is the primary way of writing computations that work for any collections in F#. There are a few ways you can work with the type:

  • You can use functions from the Seq module (such as Seq.filter, Seq.windowed etc.)
  • You can use sequence comprehensions (e.g. seq { for x in col -> x * 2 })
  • You can use the underlying (imperative) IEnumerator<'T> type, which is sometimes needed e.g. if you want to implement your own zipping of collections (this is returned by calling GetEnumerator)

This is relatively simple type and it can be used only for reading data from collections. As the result, you'll always get a value of type seq<'T> which is essentially a lazy sequence.

F# doesn't have any mechanism for transforming collections (e.g. generic function taking collection C to collection C with new values) or any mechanism for creating collections (which is available in Haskell or Scala).

In most of the practical cases, I don't find that a problem - most of the work can be done using seq<'T> and when you need a specialized collection (e.g. array for performance), you typically need a slightly different implementation anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文