请考虑例如let f x = f x in f 1
。是否定义了签名?
如果是这样,那是什么?
有人可能会争辩说,OCaml不知道它没有终止的事实,并且其类型只是被推断为'a
。正确吗?
let a b = let rec f x = f x in f 1;;
例如val a : 'a -> 'b
,尽管很清楚,应用a
时不会出现'b
答案 0 :(得分:1)
然后,当您拥有type(E) = T
时,对声音类型系统的要求是如果 E
的计算值为某个值v
,则v
为属于类型T
的值。当表达式提供值时,类型有意义,而异常和无限循环则没有。
但是类型检查器是总计的,并且为所有表达式提供类型,即使它只是一个自由类型变量也是如此。
此处返回类型不受限制,并打印为'a
。
# let f x = if x then (failwith "A") else (failwith "B");;
val f : bool -> 'a = <fun>
这里then
分支的返回类型与else
分支的类型统一:
# let f x = if x then (failwith "A") else 5;;
val f : bool -> int = <fun>
#
答案 1 :(得分:1)
读取unit -> 'a
之类的函数类型的一种方法是记住
类型变量'a
包含空类型。
例如,如果我有一个函数f
let rec f:'a. _ -> 'a = fun () -> f ()
和一个空类型
type empty = |
(* using 4.07 empty variants *)
(* or *)
type (_,_) eq = Refl: ('a,'a) eq
type empty = (float,int) eq
然后我可以将f的类型限制为unit -> empty
:
let g: unit -> empty = f
此外,在存在分支的情况下,更通用的f
类型可能很有用。
例如,我可以定义一个return
以便按顺序引发异常
提前退出for循环:
let search pred n =
let exception Return of int in
let return: 'a. int -> 'a = fun n -> raise (Return n) in
try
for i = 0 to n do
if pred i then return i
done;
None
with Return n -> Some n
在这里,return
的多态类型使得可以在上下文中使用它
预期unit
的位置。