7

I'm switching from Haskell to OCaml but I'm having some problems. For instance, I need a type definition for regular expressions. I do so with:

type re = EmptySet 
    | EmptyWord
    | Symb of char
    | Star of re
    | Conc of re list
    | Or of (RegExpSet.t * bool) ;;

The elements inside the Or are in a set (RegExpSet), so I define it next (and also a map function):

module RegExpOrder : Set.OrderedType = 
    struct
      let compare = Pervasives.compare
      type t = re
    end 
module RegExpSet = Set.Make( RegExpOrder )      
module RegExpMap = Map.Make( RegExpOrder ) 

However, when I do "ocaml [name of file]" I get:

Error: Unbound module RegExpSet

in the line of "Or" in the definition of "re".

If I swap these definitions, that is, if I write the modules definitions before the re type definitions I obviously get:

Error: Unbound type constructor re

in the line of "type t = re".

How can I solve this? Thanks!

pad
  • 41,040
  • 7
  • 92
  • 166
vegetus
  • 95
  • 5

1 Answers1

9

You can try to use recursive modules. For instance, the following compiles:

module rec M : 
sig type re = EmptySet
    | EmptyWord
    | Symb of char
    | Star of re
    | Conc of re list
    | Or of (RegExpSet.t * bool) 
end = 
struct
  type re = EmptySet 
    | EmptyWord
    | Symb of char
    | Star of re
    | Conc of re list
    | Or of (RegExpSet.t * bool) ;;
end

and RegExpOrder : Set.OrderedType = 
    struct
      let compare = Pervasives.compare
      type t = M.re
    end 
and RegExpSet : (Set.S with type elt = M.re) = Set.Make( RegExpOrder )
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • Thanks for answering! I added that definition to the top of my file. However now I have a new problem which is when I try to do patter matching of arguments of a function with elements of type M.re. For instance, this function let lf exp = match exp with M.EmptyWord -> M.EmptySet ;; gives me Error: Unbound constructor M.EmptyWord Ricardo Almeida – vegetus Dec 18 '11 at 15:41
  • The implementation of type `re` has been made abstract. Try removing the module signature `sig type re end`. Also look into `private` types, which will allow an intermediate level of hiding; outside the module you'll have to use special constructors to get values of type `re`, but you can still pattern match. – Ashish Agarwal Dec 18 '11 at 16:02
  • @user1104586 I have updated my answer to make the constructors of `M.re` visible. – Pascal Cuoq Dec 18 '11 at 17:52
  • @AshishAgarwal You can't just remove the signature. It is mandatory in a `module rec` set of module definitions, as indicated in the section of the documentation I linked to. – Pascal Cuoq Dec 18 '11 at 17:53
  • 4
    If a recursive module contains only type definitions, it is possible to not duplicate signature and implementation using the following specific pattern: `module rec M : sig .. end = M`. See eg. [this bugtracker item](http://caml.inria.fr/mantis/view.php?id=4899). – gasche Dec 18 '11 at 18:11
  • Thank you all for your contributions! Now it compiles fine. – vegetus Dec 18 '11 at 23:15