2010-10-28 1 views
6
module <name> = 
    struct 
    .. 
    end;; 


module type <name> = 
    struct (* should have been sig *) 
     .. 
end;; 
+3

Вы пытались скомпилировать свой тип модуля Name = struct ... end' перед тем, как задать вопрос? –

+0

Я просто хотел проиллюстрировать пример. Я работал над большим модулем и понял, что я не хочу отвлекать людей от актуального вопроса. –

ответ

7

Первый объявляет модуль, а второй объявляет тип модуля (он же подпись). Тип модуля содержит объявления type и val, тогда как модуль может содержать определения (например, привязки let). Вы можете использовать подпись, чтобы ограничить тип модуля, как можно больше для функции. Например,

module type T = sig 
    val f : int -> int 
end 

module M : T = struct 
    let f x = x + 1 
    let g x = 2 * x 
end 

Теперь мы имеем

# M.f 0 ;; 
- : int = 1 
# M.g 0 ;; 
Error: Unbound value M.g 

M.g является несвязанным, потому что она скрыта подписью T.

Другим распространенным способом использования типов модулей является аргументация и возврат значений функторов. Например, Map.Make функтора в the standard library принимает модуль с подписью Map.OrderedType и создает модуль с подписью Map.S

P.S. Обратите внимание, что в вопросе есть ошибка. Тип модуля объявляются с использованием

module type <name> = sig 
    ... 
end 
0

тип модуля описывает модуль. Это то же самое, что разница между .ml и .mli

3

структура (написано struct … end) представляет собой пучок определений. Любой объект на языке может быть определен в модуле: значения ядра (let x = 2 + 2), типы (type t = int), модули (module Empty = struct end), подписи (module type EMPTY = sig end) и т. Д. Модули являются обобщением структур: структура представляет собой модуль, и поэтому является functor (подумайте об этом как о функции, которая принимает модуль как аргумент и возвращает новый модуль). Модули похожи на основные значения, но живут на одном уровне выше: модуль может содержать что угодно, тогда как базовое значение может содержать только другие значения ядра¹.

подпись (написано) является связкой спецификаций (некоторые языки используют термин декларацию). Любой объект на языке может быть указан в модуле: значения ядра (val x : int), типы (type t = int), модули (module Empty : sig end), подписи (module type EMPTY = sig end) и т. Д. Типы модулей обобщают сигнатуры: тип модуля определяет модуль и тип модуля, который определяет структуру, называется сигнатурой. Типы модулей - это модули, для которых обычные типы относятся к основным значениям.

Единицы компиляции (.ml файлов) являются структурами. Интерфейсы (.mli файлов) являются подписями.

Таким образом, module Foo = struct … end определяет модуль под названием Foo, который является структурой. Это аналогично let foo = (1, "a"), который определяет значение, называемое foo, которое является парой. И module type FOO = sig … end (примечание: sig, а не struct) определяет тип модуля, называемый FOO, который является сигнатурой.Это аналогично type foo = int * string, который определяет тип, называемый foo, который является типом продукта.

¹ Это уже не так, поскольку OCaml 3.12 представил первоклассные модули, но это достаточно близко для вводного представления.