Types 将哈希表标识为OCaml中的用户定义类型

Types 将哈希表标识为OCaml中的用户定义类型,types,ocaml,Types,Ocaml,我希望能够定义一个类型(比如my_type),该类型可以识别以字符串作为键并映射到整数值的哈希表。 所以,我试过了 # type my_type = (string, int) Hashtbl.t;; 但是,当我尝试 # let a = Hashtbl.create 100;; val a : ('_a, '_b) Hashtbl.t = <abstr> # Hashtbl.add a "A" 12;; - : unit = () # a;; - : (string, int) H

我希望能够定义一个类型(比如my_type),该类型可以识别以字符串作为键并映射到整数值的哈希表。
所以,我试过了

# type my_type = (string, int) Hashtbl.t;;
但是,当我尝试

# let a = Hashtbl.create 100;;
val a : ('_a, '_b) Hashtbl.t = <abstr>
# Hashtbl.add a "A" 12;;
- : unit = ()
# a;;
- : (string, int) Hashtbl.t = <abstr>
#让a=Hashtbl.create 100;;
值a:(“a”,“b”)Hashtbl.t=
#Hashtbl.添加一个“a”12;;
-:单位=()
#a;;
-:(字符串,int)Hashtbl.t=

最后一行显示(string,int)Hashtbl.t=absr,而不是my_类型。如何确保它将哈希表的类型作为我的类型提供给我?

my\u type
只是
(string,int)Hashtbl.t
的同义词,两者都可以互换使用

您可以告诉编译器
a
属于
myu类型
,并通过以下方式获得更好的输出:

# let (a:my_type) = Hashtbl.create 100;;
val a : my_type = <abstr>
# a;;
- : my_type = <abstr>
#让(a:my_type)=Hashtbl.create 100;;
val a:my_类型=
#a;;
-:my_类型=

如果您想知道
,这意味着toplevel不知道如何打印
a
(它的内容,而不是它的类型)。

更新:抱歉,正如gasche指出的,您可以使用一个简单的类型注释来做到这一点,忘记类型强制

# type my_type = (string, int) Hashtbl.t;;
type my_type = (string, int) Hashtbl.t
# let (a : my_type) = Hashtbl.create 100;;
val a : my_type = <abstr>
#键入my_type=(string,int)Hashtbl.t;;
键入my_type=(字符串,int)Hashtbl.t
#让(a:my_type)=Hashtbl.create 100;;
val a:my_类型=

声明类型同义词并期望编译器在精确的情况下使用一个表达式或另一个表达式是没有意义的:因为它们是相等的类型,编译器将使用其中一个,而您对此几乎没有控制权

如果要强制执行类型抽象,以避免将类型
my_type
与任何其他
(string,int)Hashtbl.t
混合,则应使用标记差异的构造函数定义新类型:

type my_type = Tbl of (string, int) Hashtbl.t
let a = Tbl (Hashtbl.create 100)
let add (Tbl t) k v = Hashtbl.add t k v

您可能需要这样做(并且当您想要使用一个
Hashtbl
函数时,必须通过显式模式匹配将
my_type
的所有值转换为哈希表),或者您可能只想操作一个类型同义词,但是在后一种情况下,您不应该期望编译器输出报告任何特定类型。

这不是一个很好的建议:这里不是关于子类型,只是两个相等的类型。强制没有多大意义,就像一个简单的类型注释一样,事实上,即使是类型注释也没有什么用处。。这确实不是一个好建议。从OCAML3.11开始,您可以使用“私有类型缩写”来获得一个新类型,而不需要运行时开销(我自己从来没有检查过)。为此,您可以使用
键入my_type=private(string,int)Hashtbl.t
。在定义模块中,
my_type
只是一个普通类型的缩写。但是,在外部,您需要显式转换函数。对于一个方向,强制也起作用,例如,
t:>(string,int)Hashtbl.t
将类型为
my_type
t
强制到哈希表中。@chris:但这假设是一个模块抽象,在该抽象之外,您只有转换的一面。这里需要的是一个“不透明类型缩写”,它允许两个转换方向,但强制它们是显式的,就像“private”与通常的同义词相比所做的那样。