繁体   English   中英

Ocaml中的递归

[英]Recursion in Ocaml

我是Ocaml的新手,我正在尝试编写一个递归函数。

该函数获取一对列表并返回一对列表,例如

[(1, 4); (2, 3); (5, 9); (6, 10)]) -> ([1; 2; 5; 6], [4; 3; 9; 10])

但是编译器说: Error: This expression has type 'a list * 'b list but an expression was expected of type 'a list

在行中(unzip (List.tl m))

有人可以解释为什么我有这个错误吗? 而且有解决此问题的方法吗? 非常感谢你!

let rec unzip m =
    if List.length m = 0 then
       ([], [])
    else
       ((fst (List.hd m)) :: (unzip (List.tl m)), (snd (List.hd m)) :: (unzip (List.tl m)))
in 
    unzip m;; 

对于任何递归,您都必须注意输出类型将始终相同。

让我们看看您的unzip功能。

[(1, 4); (2, 3); (5, 9); (6, 10)]) -> ([1; 2; 5; 6], [4; 3; 9; 10])

简而言之, unzip的返回类型是def 对(元组) ,每个元素都是一个列表,对吗?


那我们来看一下你的代码

let rec unzip m =
    if List.length m = 0 then
       ([], [])
    else
       ((fst (List.hd m)) :: (unzip (List.tl m)), (snd (List.hd m)) :: (unzip (List.tl m)))
in 
    unzip m;;

您有两个分支。 第一个分支正在返回([], []) 好吧,就返回类型而言,它是正确的,因为它是一对带有两个空列表并且匹配上述返回类型。


第二支

((fst (List.hd m)) :: (unzip (List.tl m)), (snd (List.hd m)) :: (unzip (List.tl m)))

这是正确的吗?

是一对有两个元素的对,没问题,接下来让我们看一下第一个元素:

(fst (List.hd m)) :: (unzip (List.tl m))

您试图将(fst (List.hd m))(unzip (List.tl m))的头部。

但是您只能使用::将某些东西添加到列表中,因此ocaml假定(unzip (List.tl m))是列表,对吗?

但这是一个unzip功能的应用程序,显然是在一开始就描述的,您的unzip不是返回列表,而是一对(元组)。

因此,ocaml无法理解,因此会抱怨。


以上只是为了回答有关类型问题的问题。 但是您的代码有更多问题。

1.不正确使用的in

假设您有一个函数f1 您可以将其成像为母函数,这意味着它可以直接使用。 同样在f1 ,您可以声明另一个函数或变量(或更正式地说,是绑定)。 仅当在函数内部声明绑定时,才使用let...in... 如果仅具有母亲功能,则不要in使用,因为in where

在您的unzip ,您只有一个功能或绑定本身就是unzip ,并且位于顶层。 所以in没有必要。

2.递归逻辑不正确

我不知道如何在这里向您解释递归,因为它需要您阅读更多和练习更多。

但是您想法中正确的代码是

let rec unzip = function
  | [] -> ([], [])
  | (x,y)::tl -> 
    let l1, l2 = unzip tl in
    x::l1, y::l2

如果您追求的是更好的版本或尾部递归版本,则为:

let unzip l = 
  let rec unzip_aux (l1,l2) = function
    | [] -> List.rev l1, List.rev l2
    | (x,y)::tl -> unzip_aux (x::l1, y::l2) tl
  in 
  unzip_aux ([],[]) l

错误来自以下事实: (unzip ...)返回一对列表( 'a list * 'b list ),您在编写(fst ..) :: (unzip ...)

如果您使用模式匹配,那么所有这些都将写得更好。 骨架:

let rec unzip = function
  | [] -> ...
  | (x,y) :: rest ->
    let (xs, ys) = unzip rest in ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM