簡體   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