我写了这个ocaml函数:
(* int Base.List.t -> Base.Int.t x Base.Int.t *)
let min_and_max lst =
let mmax = ref Float.neg_infinity
and mmin = ref Float.infinity in
List.iter ~f:(fun v -> let fv = Float.of_int v in
if fv > !mmax then mmax := fv
else if fv < mmin then mmin := fv)
lst;
(Int.of_float !mmin, Int.of_float !mmax)
应该返回整数列表的最小值和最大值,但是在编译时会出现此错误:
File "02-exercises/24-refs/problem.ml", line 25, characters 21-23:
Error: This expression has type Base.Float.t = float
but an expression was expected of type int
错误指向该函数中的第一个if
语句。我肯定犯了一个非常明显的错误,但我看不到。
let min_and_max lst =
match lst with
| [] -> failwith "Cannot find min and max of empty list"
| v::[] -> (v,v)
| a::b::rest ->
let mmax = ref (max a b)
and mmin = ref (min a b) in
List.iter ~f:(fun v ->
if v > !mmax then mmax := v;
if v < !mmin then mmin := v)
rest;
(!mmin, !mmax)
答案 0 :(得分:2)
Base禁用多态比较:您需要使用本地open来比较>
或<
:Float.(fv > !mmax )
的浮点数。
p.s .:免费转换为float(以及使用引用)有点奇怪且不是最佳选择。
答案 1 :(得分:1)
我不明白您的编译器如何向您抛出该错误。您的代码包含一些之前应检测到的错误:
mmin
进行比较,而不是与参考内容进行比较-您错过了!
-。int_of_float
函数与Int.of_float
混淆了,但不存在。此外,该函数的逻辑原理还不够。例如,列表的第一个值将始终输入mmax
变量中,因为它将大于负无穷大。但是,如果这个值是最小值呢?
除上述内容外,在这种情况下将整数转换为浮点数是没有意义的,并且会导致精度损失和性能下降。也不需要使用引用。
这不是在OCaml上下文中进行规范的方法。在OCaml中,尝试找到最简单的解决方案很重要,因为一旦您开始复杂化类型,最终将无法解决灾难。
我为您提供了一个更简单的解决方案,它不仅具有整数功能,而且还具有构成多态函数的许可:
let min_and_max lst =
(List.fold_left (fun a b -> if a < b then a else b) (List.hd lst) lst),
(List.fold_left (fun a b -> if a > b then a else b) (List.hd lst) lst);;
这是一个优雅的选择,此外它基于终端递归。但是,在这种方案下,您可以自己重新定义功能,而无需使用预定义的功能来遍历列表。您也可以在一个回合中选择两个数字,但是这样做会有些复杂。