ocamltrieocaml-batteries

Ocaml TRIE implementation


I'm trying to use this trie implementation for ocaml: http://www.lri.fr/~filliatr/ftp/ocaml/ds/trie.ml.html

This is my implementation of module "M":

module M =
    struct     
    type key = int
    type 'a t = (int * 'a) list
    let empty = []
    let equal x y = false
    let compare f x y = 1

    let find x l = 
        let pred e = fst e == x in
        let z = List.find pred l in
        snd z

    let add x t m = (x,t)::m

    let remove x m = filter (fun e -> fst e != x) m

    let map f m = 
        let aux (x,y) = (x, f y) in
        List.map aux m

    let mapi f m =
        let aux i (x,y) = (x, f i y) in
        List.mapi aux m

    let mem x m = 
        let l = List.map snd m in
        List.mem x l

    let iter f m =
        let aux x = f (snd x) in
        List.iter aux m

    let fold f m acc1 =
        let aux acc x = f acc (snd x) in
        List.fold_left aux acc1 m               

    let is_empty m = m == empty

end;;

Ignore incorrect semantics (equal, compare, etc).

I'm using ocaml batteries, and this is how I try to make this work:

# #use "trie.ml";;
module Make :
  functor (M : Batteries.Map.S) ->
    sig
      type key = list M.key;
      type t 'a = [ Node of option 'a and M.t (t 'a) ];
      value empty : t 'a;
      value find : list M.key -> t 'a -> 'a;
      value mem : list M.key -> t 'a -> bool;
      value add : list M.key -> 'a -> t 'a -> t 'a;
      value remove : list M.key -> t 'a -> t 'a;
      value map : ('a -> 'b) -> t 'a -> t 'b;
      value mapi : (list M.key -> 'a -> 'b) -> t 'a -> t 'b;
      value iter : (list M.key -> 'a -> 'b) -> t 'a -> unit;
      value fold : (list M.key -> 'a -> 'b -> 'b) -> t 'a -> 'b -> 'b;
      value compare : ('a -> 'a -> int) -> t 'a -> t 'a -> int;
      value equal : ('a -> 'a -> bool) -> t 'a -> t 'a -> bool;
      value is_empty : t 'a -> bool;
    end
# #use "m.ml";;
module M :
  sig
    type key = int;
    type t 'a = list (int * 'a);
    value empty : list 'a;
    value equal : 'a -> 'b -> bool;
    value compare : 'a -> 'b -> 'c -> int;
    value find : 'a -> list ('a * 'b) -> 'b;
    value add : 'a -> 'b -> list ('a * 'b) -> list ('a * 'b);
    value remove : 'a -> BatEnum.t ('a * 'b) -> BatEnum.t ('a * 'b);
    value map : ('a -> 'b) -> list ('c * 'a) -> list ('c * 'b);
    value mapi : (int -> 'a -> 'b) -> list ('c * 'a) -> list ('c * 'b);
    value mem : 'a -> list ('b * 'a) -> bool;
    value iter : ('a -> unit) -> list ('b * 'a) -> unit;
    value fold : ('a -> 'b -> 'a) -> list ('c * 'b) -> 'a -> 'a;
    value is_empty : list 'a -> bool;
  end

# module X = Make(M);;
Error: Signature mismatch:
       Modules do not match:
         sig
           type key = int;
           type t 'a = list (int * 'a);
           value empty : list 'a;
           value equal : 'a -> 'b -> bool;
           value compare : 'a -> 'b -> 'c -> int;
           value find : 'a -> list ('a * 'b) -> 'b;
           value add : 'a -> 'b -> list ('a * 'b) -> list ('a * 'b);
           value remove : 'a -> BatEnum.t ('a * 'b) -> BatEnum.t ('a * 'b);
           value map : ('a -> 'b) -> list ('c * 'a) -> list ('c * 'b);
           value mapi : (int -> 'a -> 'b) -> list ('c * 'a) -> list ('c * 'b);
           value mem : 'a -> list ('b * 'a) -> bool;
           value iter : ('a -> unit) -> list ('b * 'a) -> unit;
           value fold : ('a -> 'b -> 'a) -> list ('c * 'b) -> 'a -> 'a;
           value is_empty : list 'a -> bool;
         end
       is not included in
         Batteries.Map.S
       The field `Labels' is required but not provided
       The field `Infix' is required but not provided
       The field `Exceptionless' is required but not provided
       The field `print' is required but not provided
       The field `of_enum' is required but not provided
       The field `backwards' is required but not provided
       The field `enum' is required but not provided
       The field `choose' is required but not provided
       The field `max_binding' is required but not provided
       The field `min_binding' is required but not provided
       The field `values' is required but not provided
       The field `keys' is required but not provided
       The field `filter_map' is required but not provided
       The field `filteri' is required but not provided
       The field `filter' is required but not provided
       The field `modify' is required but not provided
# 

I don't understand this error. It seems to me that types of methods in my implementation of module "M" are valid.

I also don't understand why ocaml wants fields not required by TRIE's implementation (Labels, infix, etc).


Solution

  • You must have typed something like open Batteries;; earlier in your toplevel. Because of this, module Make (M : Map.S) = struct in trie.ml is interpreted as defining a functor Make of an argument of signature Batteries.Map.S.

    Now, Batteries.Map.S contains all the types, methods, ... of the standard Map.S, so you don't notice the issue when #using trie.ml, only later when you try to apply Make. But Jean-Christophe FilliĆ¢tre intended the standard Map.S when he wrote his file. If you had compiled trie.ml instead of #using it, Map.S would have been resolved to the standard library's. Another advantage of compiling and #loading trie.ml would be that the functor to create a trie module would be named Trie.Make (again, as intended by Jean-Christophe: Make alone is ambiguous and is only used by convention inside another module that gives the context: Hashtbl.Make, Set.Make, ...)