最近我得到了代码
List.fold_left (fun acc x -> raise x ; acc) 3
我对这个具有功能性的部分应用程序完全没问题 类型
exn list -> int
的值,以及它产生警告的事实 这并不奇怪。但是,我不确定警告的一半是什么 的意思是:Warning 21: this statement never returns (or has an unsound type.)
我实际上找不到任何对此警告的引用 不归还声明的结果。甚至只有ocamlc的手册页 提到此警告的非返回语句和warnings.ml 仅将其称为
Nonreturning_statement
。我熟悉健全的概念,因为它与类型有关 系统,但类型本身本身就不健全的想法似乎 我很奇怪。
所以我的问题是:
究竟什么是不健全的类型?
当OCaml出现不合适的类型时会出现什么情况 只会发出警告而不是彻底失败?
有人发布了这个问题,在我写答案的时候,它被删除了。我相信这个问题非常有趣,值得重新发布。请考虑您可能有人愿意帮助您: - (
答案 0 :(得分:13)
首先,让我们考虑返回无关'a
的函数:我不是指let id x = x
这样的函数,因为它有类型'a -> 'a
和返回类型{{1与输入有关。我的意思是'a
和raise : exn -> 'a
等功能。
这些函数返回不相关的exit : int -> 'a
被认为永远不会返回。由于类型'a
(更准确地说是'a
)没有公民。函数唯一能做的就是终止程序(退出或引发异常)或陷入无限循环:forall 'a. 'a
。
当语句的类型为let rec loop () = loop ()
时,会提到警告21。 (实际上还有另一个条件,但我只是为了简单起见而跳过。)例如,
'a
这是警告21的主要目的。那么后半部分是什么?
即使语句实际返回,也可以报告警告21。在这种情况下,警告消息表明该语句的类型不合适。
为什么不健全?由于表达式确实返回了类型# loop (); print_string "end of the infinite loop";;
Warning 21: this statement never returns (or has an unsound type.)
的值,该值没有公民。它打破了OCaml所依赖的类型理论的基础。
在OCaml中, 有几种方法来编写具有如此不健全类型的表达式:
使用forall 'a. 'a
。它会拧紧类型系统,因此您可以编写一个类型为Obj.magic
的表达式,它返回:
'a
使用(Obj.magic 1); print_string "2"
。与external
相同,您可以为任何外部值和函数赋予任意类型:
Obj.magic
对于OCaml类型系统,不可能用不健全的类型区分非返回表达式和表达式。这就是为什么它不能排除不合理的错误。跟踪定义以告诉声明有一个不合理的类型通常是不可能的,并且即使在可能的情况下也要花费很多。