ocaml递归模式匹配

时间:2010-06-15 04:51:02

标签: ocaml matching

我正在尝试编写一个简单的递归函数,它查看列表并返回一对整数。这很容易用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 个答案:

答案 0 :(得分:5)

这里的一个问题是你返回两种不同的类型:一个是空列表的int,另一个是元组。它必须是一个或另一个。

另一个问题是您尝试向test添加1,但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;;

在这种情况下,使用累加器可以提供很多帮助。它还使函数tail-recursive,这总是很好的做法。

答案 1 :(得分:4)

离开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);;

您可以使用嵌套的匹配语句来提取元组的片段以进行修改

编辑: 我不知道Pascal Cuoq在下面的评论中提到的语法,这里是类似的代码,它更整洁,更短:

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);;

但是接受的答案仍然要好得多,尤其是尾部递归;)。