代码之家  ›  专栏  ›  技术社区  ›  smac89

Ocaml表达式类型混淆

  •  0
  • smac89  · 技术社区  · 6 年前

    我编写了这个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 回复  |  直到 6 年前
        1
  •  1
  •   bglezseoane    6 年前

    我不明白你的编译器怎么会给你这个错误。您的代码包含几个错误,应该在之前检测到这些错误:

    1. 你用错标签了。
    2. 在else臂中,您正在与ref进行比较 mmin 不是因为它的内容你错过了 ! .
    3. 你弄糊涂了 int_of_float 函数 Int.of_float ,不存在。

    另外,函数的逻辑原理也不充分。例如,列表的第一个值将始终输入 mmax 变量,因为它将大于负无穷大。但是如果这个值是最小值呢?

    除此之外,在这种情况下,将整数转换为浮点是没有意义的,并且会导致精度损失和性能下降。也没有必要使用参考文献。

    我为您提出了一个更简单的解决方案,它允许您编写多态函数,而不仅仅是整数:

    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);;
    

    它是一个优雅的选项,而且它基于终端递归。但是,在该方案中,您可以自己重新定义函数,而不必使用预定义的函数遍历列表。你也可以用一轮来选择这两个数字,但这样做会有点复杂。

        2
  •  2
  •   octachron    6 年前

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

    p、 s.:无偿转换为float(以及引用的使用)有点奇怪,也不是最优的。