非终止函数是否具有类型?

时间:2019-02-18 19:37:23

标签: functional-programming ocaml

请考虑例如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

2 个答案:

答案 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的位置。