OCaml:如何使用用户定义的类型作为Map.Make的关键?

时间:2014-04-11 03:37:08

标签: map ocaml

我有以下代码,我打算使用自定义类型Mapvariable创建location。我知道应该订购密钥类型(一些比较器功能)。我该如何添加这些规则才能使其工作?另外,我发现这里的代码很难看。我真的需要;;type末尾的module吗?

type variable = string;;
type location = int;;
module LocationMap = Map.Make(variable);;
module EnvironmentMap = Map.Make(location);;

修改 这是我的其余代码:

type variable = Variable of string
type location = Location of int
module LocationMap = Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap = Map.Make(struct type t = variable let compare = compare end)

(*file read function*)
let read_file filename =
  let lines = ref [] in
  let chan = open_in filename in
  try
    while true do
      lines := input_line chan :: !lines
    done;
    !lines
  with End_of_file ->
    close_in chan;
    List.rev !lines
in

(*get the inputs*)
let inputs = read_file Sys.argv.(1) in
for i = 0 to List.length inputs - 1 do
  Printf.printf "%s\n" (List.nth inputs i)
done;

这有语法错误。我不知道为什么。
EDIT2
我通过以下编辑来完成这项工作:

type variable = Variable of string
type location = Location of int
module LocationMap = Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap = Map.Make(struct type t = variable let compare = compare end)

(*file read function*)
let read_file filename =
  let lines = ref [] in
  let chan = open_in filename in
  try
    while true do
      lines := input_line chan :: !lines
    done;
    !lines
  with End_of_file ->
    close_in chan;
    List.rev !lines

(*get the inputs*)
let () = 
  let inputs = read_file Sys.argv.(1) in
  for i = 0 to List.length inputs - 1 do
    Printf.printf "%s\n" (List.nth inputs i)
  done;

对于很长的问题列表感到抱歉,let () =在这做什么?当我使用let定义函数时,我不需要in吗?

1 个答案:

答案 0 :(得分:2)

应用Map.Make仿函数时,需要提供包含类型和比较函数的结构:

module LocationMap =
    Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap =
    Map.Make(struct type t = location let compare = compare end)

您永远不需要在编译代码中使用;;。只有在使用顶层时才需要它,告诉它何时应该评估你到目前为止输入的内容。

有些人在编译的代码中使用;;,但你永远不需要这样做,我个人从不这样做。总有一种方法可以在不使用;;的情况下获得相同的效果。

<强>更新

let compare = compare将预先存在的OCaml函数compare(臭名昭着的多态比较函数)绑定到结构内的名称compare。因此,它创建了一个使用多态比较进行比较的Map。这通常是你想要的。

我创建了一个包含您的定义的文件(没有;;)和上面的代码,然后使用ocamlc -c进行编译。没有语法错误。我很肯定你不需要使用;;,因为我已经写了很多行代码而没有它。

请注意,我说如果从语法正确的OCaml代码中删除;;,结果总是在语法上正确。有一些习惯用法仅在您使用;;时才有效。我个人只是避免那些习语。

更新2

模块顶层的let是特殊的,没有in。它定义了模块的全局值。 OCaml将每个源文件视为一个模块(免费,我喜欢说),其名称与源文件名相同(大写)。

您实际上可以在let pattern = expression中拥有任何模式。所以let () = ...完全正常。它只是说表达式有单位类型(因此模式匹配)。