Функторы в Окамле - PullRequest
       29

Функторы в Окамле

12 голосов
/ 13 марта 2009

У меня небольшая проблема с функтором (и его результирующим типом). Ниже у меня есть функтор Set, который использует тип Ordered. Я действительно использовал set.ml, который идет с ocaml для некоторых указаний, но я, кажется, делаю все ахх правильно. Я создал модуль Ordered с целыми числами и применил его к функтору Set, чтобы получить последний модуль в этом примере кода, IntSet.

Следующая строка завершается неудачно, когда я пытаюсь вставить целое число. Я получаю следующую ошибку типа:

Error: This expression has type int but is here used with type
         SetInt.elt = Set(OrdInt).elt

Не поймите меня неправильно, система типов здесь верна. Верхний уровень сообщает, что типом SetInt.elt является Set(OrdInt).elt, но когда я выполняю те же операции для настройки набора с использованием набора, предоставленного ocaml, «та же самая» строка имеет вид SetInt.elt = OrderedInt.t. Похоже, я должен получить SetInt.elt = Ordered.t.

Это так просто, я, наверное, просто упускаю некоторые глупые детали! Argh!

Обратите внимание: я упростил функции член / вставка, поскольку эта проблема связана с типами.

module type Ordered =
  sig
    type t 
    val lt : t -> t -> bool
    val eq : t -> t -> bool
    val leq : t -> t -> bool
  end

module type S =
  sig
    type elt
    type t
    exception Already_Exists
    val empty  : t
    val insert : elt -> t -> t
    val member : elt -> t -> bool
  end

module Set (Elt:Ordered) : S = 
  struct
    type elt = Elt.t
    type t = Leaf | Node of t * elt * t
    exception Already_Exists
    let empty = Leaf
    let insert e t = t
    let member e t = false
  end

module OrdInt : Ordered =
  struct
    type t = int
    let lt a b = a < b
    let eq a b = a = b
    let leq a b = a <= b
  end

module IntSet = Set (OrdInt)

(* line that fails *)
let one_elm = IntSet.insert 1 IntSet.empty

1 Ответ

14 голосов
/ 13 марта 2009

Вам нужно изменить эти две строки

module Set (Elt:Ordered) : S = 
module OrdInt : Ordered =

до

module Set (Elt:Ordered) : S with type elt = Elt.t = 
module OrdInt : Ordered with type t = int =

Без них модули не будут иметь подписи, которые выставляют типы elt и t как int.

[Изменить]: У set.ml нет бита 'with', потому что есть sml.mli, который объявляет подпись для функтора и имеет 'with' Кроме того, OrdInt не требуется 'with', если вы явно не указали для него сигнатуру, например:

module OrdInt =

Вы также можете построить набор, определив модуль на месте:

module IntSet = Set (struct
 type t = int
 let lt a b = a < b
 let eq a b = a = b
 let leq a b = a <= b
end) 
...