Есть ли в OCaml общие функции map () / redu ()? - PullRequest
19 голосов
/ 06 ноября 2008

В Python map () работает с любыми данными, которые следуют протоколу последовательности. Это правильно, независимо от того, передаю ли я строку, список или даже кортеж.

Разве я не могу иметь свой торт в OCaml? У меня действительно нет другого выбора, кроме как посмотреть на тип коллекции, которую я использую, и найти соответствующий List.map или Array.map, Buffer.map или String.map? Некоторые из них даже не существуют! Это то, что я прошу за необычное? Я должно быть что-то упустил.

Ответы [ 4 ]

18 голосов
/ 06 ноября 2008

Самый близкий к этому модуль - модуль Enum в Аккумуляторы OCaml включены (ранее Extlib ). Enum определяет карты и складывает более Enum.t; вам просто нужно использовать преобразование в / из Enum.t для вашего типа данных. Преобразования могут быть довольно легкими, потому что Enum.t ленив.

Что вам действительно нужно, так это классы типов в стиле Haskell , такие как Foldable и Functor (которые обобщают «карты»). Библиотеки Haskell определяют экземпляры Foldable и Functor для списков, массивов и деревьев. Другим подходящим методом является подход "Scrap Your Boilerplate" к общему программированию. Поскольку OCaml не поддерживает классы типов или высший тип полиморфизма , я не думаю, что вы сможете выразить подобные шаблоны в его системе типов.

11 голосов
/ 06 мая 2009

В OCaml есть два основных решения:

  1. Жак Гарриг уже реализовал синтаксически легкий, но неэффективный подход для многих структур данных несколько лет назад. Вы просто заключаете коллекции в объекты, которые предоставляют метод map. Затем вы можете сделать collection#map, чтобы использовать функцию карты для любого вида коллекций. Это более общее, чем ваши требования, поскольку оно позволяет заменять различные типы структур данных во время выполнения . Однако на практике это не очень полезно, поэтому этот подход никогда не получал широкого распространения.

  2. Синтаксически более тяжелое, но эффективное, надежное и статичное решение заключается в использовании функторов для параметризации вашего кода в структуре данных, которую вы используете. Это упрощает повторное использование кода с различными структурами данных. Посмотрите переводы Маркуса Моттла OCaml книги Окасаки «Чисто функциональные структуры данных» для некоторых замечательных примеров.

Если вы не ищете такой мощности и просто хотите краткости, то, конечно, вы можете просто создать псевдоним модуля с более коротким именем (например, модуль S = String).

1 голос
/ 06 ноября 2008

Проблема в том, что каждый контейнер имеет свое представление и требует иного кода для отображения / сокращения для его итерации. Вот почему есть отдельные функции. Большинство языков предоставляют некоторый общий интерфейс для контейнеров (такой как протокол последовательности, который вы упомянули), поэтому такие функции, как map / lower, могут быть реализованы абстрактно, но это не сделано для упомянутых вами типов.

0 голосов
/ 29 ноября 2008

Пока вы определяете сравнение типов t и val (: t-> t-> int) в своем модуле, Map.Make выдаст вам нужную карту.

...