开发者

Abstracting over Collection Types

开发者 https://www.devze.com 2023-02-27 14:42 出处:网络
Is there a possibility of writing functions which are generic in respect to collection types they support other than using the seq module?

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 colle开发者_Go百科ction functions.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消