簡體   English   中英

使用OCaml遞歸並解壓縮

[英]Recursion using OCaml and unzip

我進行了模式匹配,並且工作正常:

let rec unzip  l = 
    match l with
    |[] -> ([], [])
    |(x,y)::tail -> 
    let (first, second) = unzip tail in 
      (x::first, y::second)

但是我該如何使用地圖或向右折疊(僅提示,請勿告訴我如何實際操作)

我在考慮以下方面:

let unzip : ('a * 'b) list -> 'a list * 'b list = let (first,second) = map (fun (x,y) -> (x::first, y::second) );;

但是出現語法錯誤

如果您查看List.map的類型:

# List.map;;
- : ('a -> 'b) -> 'a list -> 'b list = <fun>

您會看到它總是返回一個列表。 由於要返回一對列表,因此不能使用List.map 您可以使用折疊。 或者,您可以List.map對中的每個列表調用一次List.map

更新

讓我們使用List.fold_left ,我認為這要容易一些。

fold_left的本質是找出一個執行計算步驟的函數。 該函數將到目前為止累積的答案以及該列表的一個新元素取走。 返回值是新的累積答案。 如果可以定義這樣的功能,則可以將其折疊在輸入列表上以獲得完整的答案。

一種看待這種情況的方法是,您的函數正是作為for語句主體出現的函數。 for的主體也執行一個計算步驟。

假設我要添加一個整數列表。 因此,我想要的函數將到目前為止的累積答案(一個int),列表中的下一個值(一個int)作為新值,並返回新的累積答案(兩個int之和)。 因此,要折疊的函數如下所示:

let foldme a b = a + b

如果將其折疊為一個整數列表,您將得到總和:

# let foldme a b = a + b;;
val foldme : int -> int -> int = <fun>
# List.fold_left foldme 0 [3; 5; 7; 11];;
- : int = 26

如果要反轉列表,則需要一個函數,該函數可將答案(到目前為止為列表的第一部分)與列表的新元素相乘,然后返回帶有在開頭添加的新值的反轉。 因此,您想要的功能如下所示:

let foldme2 a b = b :: a

如果將其折疊在列表上,則會得到列表的反面:

# let foldme2 a b = b :: a;;
val foldme2 : 'a list -> 'a -> 'a list = <fun>
# List.fold_left foldme2 [] [4; 5; 6; 7];;
- : int list = [7; 6; 5; 4]

如果您可以找出執行一步計算的函數,則可以找出如何進行折疊。 確實需要一段時間才能做到。

let f (l,s) (x,y) = (x::l,y::s);;
let unzip l = List.fold_left f ([],[]) (List.rev l);;

您可以使用List.map兩次:一次fst並曾經與snd 但是,我建議您花些時間了解List.fold_rightList.fold_left因為它們在許多情況下都很有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM