2013-03-10 53 views
9

我希望能够定义一个类型(比如my_type),它可以标识包含字符串作为键的哈希表并将其映射为整数值。
所以,我想将哈希表标识为OCaml中的用户定义类型

# 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> 

最后一行显示的(字符串,整数)Hashtbl.t =文摘代替my_type。我怎样才能确保它给我的散列表的类型为my_type?

回答

1

my_type只是(string, int) Hashtbl.t的同义词,您可以互换使用。

你可以告诉编译器amy_type型的,并得到更好的输出,这种方式:

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

如果你想知道关于<abstr>,这意味着顶层不知道如何打印a(其内容,而不是其类型)。

2

更新:对不起,因为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> 
+1

这不是一个很好的建议:它不是关于子类型,而是简单的两种类型。强制并没有多大意义,因为简单的类型注释会这样做,实际上即使是类型注释也没有多大用处。 – gasche 2013-03-10 15:06:55

+0

你是对的,我忘记了类型注释..这确实不是一个好建议.. – octref 2013-03-10 15:44:29

9

这是没有意义的声明类型的同义词,并期望编译器在精确的情况下使用一个表达式或其他表达式:由于它们是相同的类型,因此编译器将使用其中一个表达式,并且对此没有太大控制。

如果要强制类型抽象,从而不与任何其他(string, int) Hashtbl.t混合型my_type,你应该定义一个新的类型与构造标记的区别:

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的值转换成哈希表的代价,或者你可能只想操作一个类型同义词,但在后一种情况下,你不应该期望编译器输出报告任何特定的类型。

+1

从OCaml 3.11开始,你可以使用“私有类型缩写”来获得一个没有运行时间开销的新类型(我从来没有自己检查过)。为此,您可以使用'type my_type = private(string,int)Hashtbl.t'。在定义模块里'my_type'只是一个简单类型的缩写。但是,外部需要显式转换功能。对于一个方向,强制也起作用,例如't:>(string,int)Hashtbl.t'将'my_type'类型的't'强制转换为散列表。 – chris 2013-03-11 04:07:14

+0

@chris:但是这假设了一个模块抽象,在这之外你只有一个转换的一面。这里需要的是一个“不透明的类型缩写”,它允许*两个*转换方向,但强制它们是明确的,因为“私有”与通常的同义词相比。 – gasche 2013-03-11 05:43:42

相关问题