迷彩表情类型混淆

时间:2018-09-16 15:41:59

标签: function tuples ocaml

我写了这个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)

2 个答案:

答案 0 :(得分:2)

Base禁用多态比较:您需要使用本地open来比较><Float.(fv > !mmax )的浮点数。

p.s .:免费转换为float(以及使用引用)有点奇怪且不是最佳选择。

答案 1 :(得分:1)

我不明白您的编译器如何向您抛出该错误。您的代码包含一些之前应检测到的错误:

  1. 您误用了标签。
  2. 在else分支中,您要与参考mmin进行比较,而不是与参考内容进行比较-您错过了!-。
  3. 您将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);;

这是一个优雅的选择,此外它基于终端递归。但是,在这种方案下,您可以自己重新定义功能,而无需使用预定义的功能来遍历列表。您也可以在一个回合中选择两个数字,但是这样做会有些复杂。