OCaml 期望有类型单元

OCaml expected to have type unit

当尝试 运行 OCaml 中的以下函数时:

let rec func1 o_list =
    match o_list with
    | [] -> []
    | h::t -> let (nt,inner_list) = h in
      if check_if_clear inner_list then
        [nt,inner_list]::clear_rules
      func1 t
;;

程序输出错误

Characters 139-141: [nt,inner_list]::clear_rules

Error: This variant expression is expected to have type unit The constructor :: does not belong to type unit

您还可以假设函数 check_if_clear 目前总是 returns trueo_list 是 pair 的列表,pair 本身包含一个元素和一个列表。 所以它是这样的 [ 'x , ['a,'b,'c]]clear_rules 一开始只是一个空列表。

我设法以另一种方式解决了我面临的问题,我没有尝试使用某些外部列表,而是将我的函数设为 return 所需的列表。这是代码

let rec func1 o_list clear_list =
match o_list with

| [] -> clear_list
| h::t -> let (nt,inner_list) = h in
if check_if_clear inner_list then
func1 t ([nt,inner_list]::clear_list)
else
func1 t clear_list
;;

您的原始示例在 clear_rules 之后似乎缺少一个分号。一旦插入并带有附加功能的存根,错误消息就可以重现。原因如下:

if-expression

then 分支
if check_if_clear inner_list then
    [nt,inner_list]::clear_rules

returns ('nt_type, 'inner_list_type) list list 类型的值;这是因为 [nt, inner_list] 构造了对 (nt, inner_list) 的单个项目列表,然后 cons 运算符 :: 使其成为列表的头部。所以,then分支returns一个non-unit类型。

相反,else 分支(由于不存在)具有类型单元(即没有实际值)。但在 OCaml 中,表达式的 thenelse 分支的类型必须匹配(即属于相同类型或公共超类型的子类型);因此,没有 else 分支的 if 表达式始终具有类型单元,此类表达式的 then 分支也是如此。因为它不是你的情况,编译器告诉你(以迂回的方式),通过注意 cons 运算符 :: 具有不同的类型(它创建一个列表和 returns 它)它推断出的单位类型。

我从你的评论中怀疑你的意图不是创建一个列表,而是执行一些有副作用的操作。为此,您可能需要以不同的方式编写该操作。