Абстрагирование по типам коллекций - PullRequest
0 голосов
/ 20 апреля 2011

Существует ли возможность написания функций, которые являются общими для типов коллекций, которые они поддерживают, кроме использования модуля seq?

Цель - не прибегать к копированию и вставке при добавлении новых функций сбора.

Ответы [ 2 ]

2 голосов
/ 21 апреля 2011

Обобщенное программирование с коллекциями может быть выполнено так же, как и обычное программирование в целом: Использование обобщений.

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 Хотя эта функция включена только для базовой библиотеки, она не должнапроблема в том, чтобы изменить компилятор, чтобы разрешить его в вашем коде.Это возможно, потому что исходный код компилятора открыт.

1 голос
/ 20 апреля 2011

Тип seq<'T> является основным способом написания вычислений, которые работают для любых коллекций в F #.Существует несколько способов работы с типом:

  • Вы можете использовать функции из модуля Seq (например, Seq.filter, Seq.windowed и т. Д.)
  • Вы можете использовать понимание последовательности (например, seq { for x in col -> x * 2 })
  • Вы можете использовать базовый (императивный) тип IEnumerator<'T>, который иногда необходим, например, если вы хотите реализовать собственное архивирование коллекций (это возвращаетсяВызов GetEnumerator)

Это относительно простой тип, и его можно использовать только для чтения данных из коллекций.В результате вы всегда получите значение типа seq<'T>, которое по сути является ленивой последовательностью.

F # не имеет никакого механизма для преобразования коллекций (например, универсальная функция, принимающая коллекцию C в коллекциюC с новыми значениями) или любой механизм создания коллекций (который доступен в Haskell или Scala).

В большинстве практических случаев я не вижу проблем - большая часть работы можетсделать это с помощью seq<'T>, и когда вам нужна специализированная коллекция (например, массив для производительности), вам, как правило, нужна немного другая реализация.

...