繁体   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