如何报告警告21
首先,让我们考虑返回不相关的'a
类型的函数:我并不是指像let id x = x
这样的函数,因为它的类型为'a -> 'a
,返回类型'a
与输入相关。我指的是像raise: exn ->'a
和exit: int ->'a
这样的函数。
这些返回不相关'a
类型的函数被认为是永远不会返回的。因为类型'a
(更确切地说是forall 'a.'a
)没有任何值。这些函数能做的事情只有终止程序(使用exit或引发异常)或进入无限循环:let rec loop() = loop()
。
当语句的类型为'a
时,就会提到警告21。(实际上还有另一个条件,但为了简洁起见,我跳过了。)例如,
# loop (); print_string "end of the infinite loop";;
Warning 21: this statement never returns (or has an unsound type.)
这是警告21的主要目的。那么后半部分是什么?
“不安全的类型”
即使语句实际上返回某些东西,警告21也可能被报告。在这种情况下,与警告信息所示一样,语句具有不安全的类型。
为什么是不安全的?因为该表达式返回forall 'a. 'a
类型的值,这个类型没有对应的实例。它破坏了OCaml依赖的类型理论基础。
在OCaml中,有几种写出这种不安全类型表达式的方式:
使用Obj.magic
。它破坏了类型系统,因此你可以编写一个类型为'a
的表达式,它返回:
(Obj.magic 1); print_string "2"
使用external
。和 Obj.magic
一样,你可以给任何外部值和函数指定任意类型:
使用external
。和Obj.magic
类似,您可以为任何外部值和函数指定任意类型:
external crazy : unit -> 'a = "%identity"
let f () = crazy ()
let _ = f (); print_string "3"
对于OCaml类型系统来说,它无法区分非返回表达式和具有不合规类型的表达式。这就是为什么它不能将不合规的内容作为错误排除的原因。即使可能,追踪定义以确定语句是否具有不合规类型也通常是不可能的,甚至会耗费大量成本。