對於任何遞歸,您必須注意輸出類型將始終相同。
讓我們來看看你的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
你真好!非常感謝你!當我讀到模式匹配和遞歸時,他們非常相似,實際上他們是相同的,但我認爲是相同的,但代碼格式不同 –