ocaml рекурсивное сопоставление с образцом

Я пытаюсь записать простую рекурсивную функцию, которые просматривают список и возвращают пару целого числа. Это легко записать в c/c ++/java, но я плохо знаком с ocaml так так или иначе трудно для обнаружения решения, должного вводить конфликт

это должно идти как..

let rec test p l = ... ;;
val separate : (’a -> bool) -> ’a list -> int * int = <fun>
test (fun x -> x mod 2 = 0) [-3; 5; 2; -6];; 
- : int * int = (2, 2)

таким образом, проблема состоит в том, как может я рекурсивно возвращаемое значение на кортеже..

7
задан jaco0646 15 November 2018 в 14:48
поделиться

2 ответа

На какое-то время был вдали от OCaml, но я думаю, что это поможет в отношении описания REALFREE в комментарии

let rec test l = 
  match l with 
      [] -> (0,0) 
    | x::xs -> 
        if x > 0 then match (test xs) with (x,y) -> (x+1, y)
        else  match (test xs) with (x,y) -> (x, y+1);;

. Вы можете использовать вложенные операторы сопоставления для извлечения частей кортеж для изменения

РЕДАКТИРОВАТЬ: Я не знал о синтаксисе Паскаль Куок, упомянутом в его комментарии ниже, вот такой код, он более аккуратный и немного короче:

let rec test l = 
  match l with 
      [] -> (0,0) 
    | x::xs -> 
    if x > 0 then let (x,y) = test xs in (x+1, y)
    else let (x,y) = test xs in (x, y+1);;

Но принятый ответ все же намного лучше, особенно с хвостовой рекурсией;).

4
ответ дан 7 December 2019 в 03:11
поделиться

Одна из проблем здесь в том, что вы возвращаете два разных типа: int для пустого списка или кортеж в противном случае. Должно быть либо одно, либо другое.

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

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

Я предполагаю, что вы хотите подсчитать положительные числа в списке, в этом случае вы можете написать так:

let rec test l = 
    match l with [] -> 0
   | x::xs -> if x > 0 then 1 + (test xs)
              else test xs;;

Обновление: поскольку вы отредактировали вопрос, чтобы прояснить проблему, измените приведенный выше код следующим образом:

let test l =
  let rec test_helper l pos nonpos = 
    match l with [] -> (pos, nonpos)
   | x::xs -> if x > 0 then test_helper xs 1+pos, nonpos
              else test_helper xs pos 1+nonpos
  in test_helper l 0 0;;

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

5
ответ дан 7 December 2019 в 03:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: