Путаница типа выражения Ocaml - PullRequest
       12

Путаница типа выражения Ocaml

0 голосов
/ 16 сентября 2018

Я написал эту функцию 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 голосов
/ 17 сентября 2018

Я не понимаю, как ваш компилятор выдает эту ошибку. Ваш код содержит несколько ошибок, которые он должен обнаружить раньше:

  1. Вы неправильно используете метку.
  2. В другой руке вы сравниваете с ref 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);;

Это элегантный вариант, кроме того, он основан на терминальной рекурсии. Тем не менее, по этой схеме вы можете переопределить функции самостоятельно, не используя предопределенные для просмотра списков. Вы также можете выбрать два числа одним раундом, но это будет несколько сложнее.

0 голосов
/ 16 сентября 2018

База отключает полиморфное сравнение: вам нужно использовать локальное открытие для сравнения чисел с > или <: Float.(fv > !mmax ).

ps: бесплатное преобразование в число с плавающей точкой (и использование ссылок) немного странно и неоптимально.

...