ocaml рекурсивное сопоставление с образцом - PullRequest
7 голосов
/ 15 июня 2010

Я пытаюсь написать простую рекурсивную функцию, которая просматривает список и возвращает пару целых чисел. Это легко написать на 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)

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

Ответы [ 2 ]

5 голосов
/ 15 июня 2010

Одна проблема здесь в том, что вы возвращаете два разных типа: 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;;

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

4 голосов
/ 15 июня 2010

Немного отошел от 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);;

Вы можете использовать вложенные операторы match, чтобы вытащить части кортежаизменить

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

...