Реализация быстрой сортировки в OCaml: не понимаю, что происходит не так?

#functional-programming #ocaml #quicksort

#функциональное программирование #ocaml #быстрая сортировка

Вопрос:

Я пытаюсь реализовать алгоритм быстрой сортировки в OCaml, и я думал, что он у меня есть, но он не компилируется, и я просто не могу понять, что с ним не так. Вот мой код:

 let rec quicksort list =
    match list with
    [] -> []
    |h::t -> append((quicksort (filter (largerthan h)
    t))(quicksort(filter (smallerthan h) t)));;

let largerthan x y =
    x<y;;

let smallerthan x y =
    x>y;;

let rec append x y =
match x with
[] -> y
| h::t -> h:: append t y;;  

let rec filter f list =
   match list with
   [] -> []
   |h::t -> (if f h = true then h:: filter f t else filter f t);; 
  

Теперь, когда я пытаюсь использовать это в OCaml, появляется сообщение «Ошибка: это выражение имеет тип ‘a -> ‘b
но ожидалось выражение типа «a», указывающее на последнюю строку моей функции быстрой сортировки.

Кто-нибудь знает, что происходит не так??

Большое спасибо!

Линус

Редактировать: Хорошо, я избавился от исходной ошибки (спасибо ADEpt :)). Однако теперь функция просто выводит пустой список независимо от входных данных… Кто-нибудь знает, что там происходит??

Комментарии:

1. вам не нужно для большего, просто используйте ( < ) (с paren). То же самое верно для меньшего размера, чем (с использованием ( > )).

2. Обратите также внимание, что на самом деле это не будет быстрая сортировка, потому что добавление происходит медленно (первая часть списка будет собрана дважды …)

3. Обратите также внимание, что append и filter уже доступны в базовой библиотеке, как (@) (инфиксный оператор, xs @ yx ) и List.filter соответственно.

Ответ №1:

У вас есть дополнительные скобки в вызове «применить». Вместо:

append((быстрая сортировка (фильтр (больше, чем h) t))(быстрая сортировка (фильтр (меньше, чем h) t))

Напишите это:

добавить (быстрая сортировка (фильтр (больше, чем h) t)) (быстрая сортировка (фильтр (меньший, чем h) t))

Комментарии:

1. или даже лучше это: let left = quicksort (filter (largerthan h) t) in let right = quicksort (filter (smallerthan h) t) in append left right (с правильными окончаниями строк, которые я не уверен, что смогу вставить в комментарий; это выглядит намного более читабельным)

2. Спасибо! Это устранило ошибку. Однако сейчас я просто получаю пустой список в качестве выходных данных… Кто-нибудь знает, что там происходит не так? 🙂

3. Вам нужно превратить ‘largetthan’ и ‘smallerthan’ в ‘largerthan’ и ‘smallerorequalthen’ 🙂 В противном случае нет подсписка, содержащего ‘h’

Ответ №2:

Что касается вашего «второго» вопроса: вы забыли добавить h в отсортированный список….

Ответ №3:

OCaml компилирует вашу программу в том порядке, в котором вы ее передаете. В этом вопросе все очень строго. если вы что-то используете, вам нужно указать это, прежде чем использовать. Если вы замените определение, впоследствии будет использоваться новое определение, но до этого старое.

Если брать ваш код сверху вниз, вот что получается:

 let rec quicksort list =
    match list with
    [] -> []
    |h::t -> append((quicksort (filter (largerthan h)
    t))(quicksort(filter (smallerthan h) t)));;
  

На данный момент нет определения largerthan , smallerthan filter or append , поэтому компилятор не знает, что с этим делать.

Измените порядок вашего кода, и несколько проблем исчезнут.

Комментарии:

1. Также обратите внимание: попробуйте использовать методы из стандартной библиотеки или какую-нибудь хорошую замену стандартной библиотеки (например, батарейки), где это возможно. filter и append там уже присутствуют.

2. Привет, спасибо за объяснение. Тем не менее, я только что разместил функции в этом порядке здесь, в моих исходных файлах порядок правильный :).

3. ОК. Всегда указывайте код, в котором проявляется проблема, чтобы не вводить в заблуждение других, когда предоставляемый вами код содержит дополнительные проблемы.