OCaml:变体类型和模块定义之间的循环

veg*_*tus 7 ocaml module variants

我正在从Haskell切换到OCaml,但我遇到了一些问题.例如,我需要正则表达式的类型定义.我这样做:

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

Or中的元素在一个集合(RegExpSet)中,所以我接下来定义它(以及map函数):

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

但是,当我做"ocaml [文件名]"时,我得到:

Error: Unbound module RegExpSet
Run Code Online (Sandbox Code Playgroud)

在"re"的定义中的"Or"行.

如果我交换这些定义,也就是说,如果我在重新定义类型之前编写模块定义,我显然会得到:

Error: Unbound type constructor re
Run Code Online (Sandbox Code Playgroud)

在"type t = re"的行中.

我怎么解决这个问题?谢谢!

Pas*_*uoq 9

您可以尝试使用递归模块.例如,以下编译:

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 )
Run Code Online (Sandbox Code Playgroud)

  • 如果递归模块仅包含类型定义,则可以使用以下特定模式不复制签名和实现:`module rec M:sig .. end = M`.见例如.[这个bugtracker项目](http://caml.inria.fr/mantis/view.php?id=4899). (4认同)