Расширение модуля OCaml - PullRequest
3 голосов
/ 01 июля 2019

Есть ли способ добавить функции в уже существующий модуль в OCaml?

В частности, у меня есть модуль Loc, который отслеживает местоположения в исходном файле. У меня также есть модуль с именем Ast, который представляет абстрактное синтаксическое дерево некоторого кода. Я хочу, чтобы метод Loc.of_ast был определен в ast.ml, и, следовательно, расширение Loc. Есть ли способ сделать это?

Примечание: Это может быть проблема XY. Причина, по которой я склонен полагать, что такие расширения модулей возможны, заключается в том, что в Батареях есть методы, такие как String.of_int и Int.of_string, что означает, что эти модули являются взаимно рекурсивными. Конечно, они не все полностью определены в одном файле ...

Ответы [ 2 ]

3 голосов
/ 02 июля 2019

Есть ли способ добавить функции в уже существующий модуль в OCaml?

Нет.Модули являются герметичными и не расширяемыми объектами (в отличие от объектов).

В частности, у меня есть модуль Loc, который отслеживает местоположения в исходном файле.У меня также есть модуль под названием Ast, который представляет абстрактное синтаксическое дерево некоторого кода.Я хочу, чтобы метод Loc.of_ast был определен в ast.ml, и, следовательно, расширение Loc.Есть ли способ сделать это?

Обычным способом было бы добавить эту функцию в модуль Ast, например, Ast.to_loc, который будет извлекать местоположение из дерева.Если вы не хотите, чтобы ваш Ast модуль зависел от Loc, просто поместите его в отдельный модуль, например, Ast_support, который вы можете использовать в коде, в котором вы не боитесь ввести дополнительную зависимость (хотя, похоже, ваш Ast модуль уже использует модуль Loc).

Ваше намерение поместить функцию of_ast в модуль Loc, вероятно, зависит от некоторого фона ООП, где операции над структурой данных обычно реализуются как функции-члены или методы.Однако даже в языках ООП, таких как C ++, всегда существует дилемма между использованием большего числа абстракций, нарушающих функции-члены, а не только автономной функцией, причем последняя обычно предпочтительнее.Другие языки, которые не обеспечивают какой-либо структуризации помимо классов (например, Java), вы обычно заканчиваете раздутыми интерфейсамиНет никакой необходимости доводить эти вредные привычки до OCaml :) Кроме того, OCaml разработан таким образом, что он будет противостоять плохим практикам и поощрять хорошие.В нашем случае Loc.of_ast ни в коем случае не является частью интерфейса местоположения.Также ему не нужен доступ к внутренней реализации структур данных, определенных (и я надеюсь, что они будут абстрагированы) в модуле Loc.Он может принадлежать модулю Ast, особенно если он используется в представлении данных вашего Ast.

3 голосов
/ 01 июля 2019

Что вы можете сделать, это создать новый модуль, называемый существующим модулем, и include все функции существующего модуля в свой новый. Новый модуль затеняет существующий, и вы можете использовать все новые функции.

Это как Батареи это делает , кстати.

module List = struct
  include List

  let empty = []
end;;

List.empty;;
(* - : 'a list = [] *)
...