我正在尝试通过附加到列表来创建唯一列表,但是我收到此错误。
Error: This expression has type 'a list
but an expression was expected of type unit
in_list 是一个布尔函数,用于检查值是否在列表中。
if(in_list x seen_list) then print_string("Already found") else seen_list@x in
List.iter uniq check_list;;
似乎必须为追加函数修复一些小的语法错误。建议?
TL;DR:列表在 OCaml 中是不可变的
根据您的代码,您似乎认为列表在 OCaml 中是可变的,但事实并非如此。 因此seen_list@x
计算一个新列表,但不会更改seen_list
。
您可以将代码更改为
let uniq seen_list x =
if in_list x seen_list then
(Printf.printf: "uniq: %d: Already seen.n" x; seen_list)
else x :: seen_list
in
List.fold_left uniq [] check_list
uniq
函数将整数列表映射到不重复的整数列表,并记录它跳过的条目。
我想,这段代码显然是用来学习的,但是你应该知道,它很可能实现了画家Shlemiel的算法。
这是一个类型错误,而不是语法错误。
OCaml 函数必须始终返回相同类型的结果。现在,当项目在列表中时,您的函数尝试返回与项目不在列表中不同的类型。
具体来说,当项目已经存在时,您的函数调用 print_string
,返回 ()
。这称为unit
,是一个不表示有趣值的占位符。当该项尚不存在时,函数将返回类型为 'a list
的值。几乎可以肯定的是,您需要做的是在所有情况下返回一个列表。
如果不看到更多代码,很难说更多,但处理这种情况的最常用方法是在项目已经存在时返回旧列表,当项目不存在时返回新的、更长的列表。
更新
此代码中有很多事情需要修复,但这就是我假设的练习的重点。
你的下一个问题似乎是List.iter
是一个命令式函数,即它想要做某事而不是产生结果。因此,它遍历列表的函数应该返回单位(如上所述)。您改用函数 uniq
,它返回一个列表。
如果你想使用像 List.iter
这样的高阶函数,这是优秀的 OCaml 风格,你将需要使用折叠(List.fold_left
或List.fold_right
),其目的是累积结果。