Понимание рекурсии Basi c в OCaml - PullRequest
0 голосов
/ 05 мая 2020

Привет, ребята, я пытаюсь создать простой рекурсивный метод, который просто принимает аккумулятор и целевое значение. Затем добавьте единицу в аккумулятор, пока она не достигнет целевого значения. Я новичок в Ocaml, но имею приличный опыт работы в java.

Я написал небольшой фрагмент кода, который показывает, что я хочу сделать в java:

    public static int rec(int acc,int target) {
        if (acc == target) {
            return 0;
        } else {
            return rec(acc+1, target);
        }
    }

вот моя попытка воспроизвести c этот код в Ocaml:

  let h_sequence x =
      let rec helper acc x = function
      | acc -> x
      | _ -> helper acc+1 x
      in
      helper 0 x;;

однако я получаю следующую ошибку:

Error: This expression has type 'a -> 'b -> 'a
       but an expression was expected of type int

Вот как я пытаюсь понять код Ocaml. Итак, у нас есть функция h_sequence с параметром x. Внутри функции h_sequence у нас есть рекурсивная функция с именем helper, которая имеет два параметра a cc и x. Если a cc = x, верните x. В противном случае начните рекурсию с передачи помощника, добавьте его к a cc и затем верните x. И после in он передает вспомогательную функцию, устанавливая 0 для a cc и устанавливая x как x. Пожалуйста, дайте мне знать, если мой logi c выключен. Любая помощь будет высоко ценится!

редактировать новый код:

  let h_sequence x =
      let rec helper acc x = 
        if acc = x then
            acc
        else
            helper (acc+1) x
      in
      helper 0 x;;

Ответы [ 2 ]

1 голос
/ 05 мая 2020

... у нас есть рекурсивная функция с именем helper, которая имеет два параметра a cc и x.

Вы получаете сообщение об ошибке, потому что рекурсивная функция helper действительно имеет три «параметра»: acc, x и еще один «параметр», сопоставленный с помощью function. Сообщение об ошибке дало вам эту подсказку ('a -> 'b -> 'a).

Давайте теперь посмотрим на функцию helper:

let rec helper acc x = function
    | zzz -> x  (* Equivalent to `| _ -> x` *)
    | _ -> helper acc+1 x

Ошибки:

  1. function выполняет сопоставление с образцом. Все будет соответствовать образцу zzz, что означает, что следующий образец (| _ -> helper acc+1 x) бесполезен, потому что он никогда не будет сопоставлен. Обратите внимание, что я изменил имя шаблона с вашего acc на zzz, чтобы подчеркнуть, что function действительно соответствует шаблонам.

  2. helper acc+1 x эквивалентно (helper acc) + 1 x, чего вы не хотите. Вместо этого должно быть helper (acc+1) x.

Решение

let rec helper acc x = 
    if acc >= x then 0
    else helper (acc+1) x

Вы должны использовать >= вместо = для обработки случая, когда x отрицательный.

1 голос
/ 05 мая 2020

Как говорит @Flux, ваша вспомогательная функция имеет 3 параметра. Вы также должны знать, что шаблон acc будет соответствовать всем значениям. Шаблоны состоят в основном из констант, и любые имена, появляющиеся в шаблоне, будут соответствовать (и будут связаны) с любым соответствующим значением.

Чтобы сравнить x с acc, вы должны просто использовать оператор if.

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

let rec helper acc x =
    if x = acc then (* One of the cases *)
    else (* The other case *)
...