我尝试在 Ocaml 中为列表中的每个元素添加 1 有什么问题吗?

问题描述 投票:0回答:3

我不明白我收到的错误消息或我正在尝试做的事情出了什么问题

我只想使用 List.fold_left 将我的 add1 函数应用于此列表 [1,2,3]

我的 add1 函数应该只为每个元素加 1,所以我会得到 [2, 3, 4]

我做这个练习的主要目标只是试验 List.fold_left。我实际上并不关心加 1,我只是选择该函数,因为它看起来很容易编写(我是 ocaml 初学者)。

我的最终目标实际上是使用 List.fold_left 和已在其他地方编写的函数填充空 StringMap 的键,因此如果有人对此有深入了解,我们将不胜感激

这是第一次尝试(我尝试了两次)

let rec add1 = function
  | [] -> []
  | h::t -> (h+1)::(add1 t) in List.fold_left add1 [1, 2, 3];;

这是第二次尝试

 let a(b) =
let rec add1 = function
  | [] -> []
  | h::t -> (h+1)::(add1 t)
in 
let c = List.fold_left add1 b
in a [1,2,3];;
ocaml
3个回答
2
投票

我认为你应该从:

开始
let add x = x + 1

然后构建一个函数,通过 List.fold_left 将函数应用于列表:

let apply_f_to_list_elements fn lst = (*use List.fold_left here*)

您确定要 List.fold_left 而不是 List.map 吗?


1
投票

它可能会帮助您了解如何实施

fold_left

let rec fold_left f init lst =
  match lst with
  | [] -> init
  | x::xs -> fold_left f (f init x) xs

因此,考虑一下当像 sum 函数这样的函数以

fold_left
的形式实现时,会发生什么。

let sum lst = 
  fold_left (+) 0 lst

如果我们评估

sum [1; 2; 3; 4]

sum [1; 2; 3; 4]
fold_left (+) 0 [1; 2; 3; 4]
fold_left (+) (0 + 1) [2; 3; 4]
fold_left (+) (1 + 2) [3; 4]
fold_left (+) (3 + 3) [4]
fold_left (+) (6 + 4) []
10

我们可以用

map
来定义
fold_left

let map f lst =
  let f' init x = f x :: init in
  fold_left f' [] lst

我们来评价一下

map (fun x -> x + 1) [5; 2; 6]

map (fun x -> x + 1) [5; 2; 6]
fold_left f' [] [5; 2; 6]
fold_left f' (5 + 1 :: []) [2; 6]
fold_left f' (2 + 1 :: [6]) [6]
fold_left f' (6 + 1 :: [3; 6]) []
[7; 3; 6]

现在,由于我们解构和创建列表的方式,结果是相反的。我们可以通过反转结果列表来克服这个问题。

fold_left

或使用 
let map f lst = let f' init x = f x :: init in let lst' = fold_left f' [] lst in List.rev lst'

运算符:

|>

将其提升到新的水平

在每次迭代中,

let map f lst = let f' init x = f x :: init in let |> fold_left f' [] |> List.rev

将列表和累加器中的第一个元素转换为下一次迭代的累加器。如果您想将此概念应用到您的

fold_left
模块,请考虑
StringMap
生成一个空的
StringMap.empty
,以及
StringMap.t
接受
key
、关联的 value 和现有映射,并返回添加了映射的新地图。 您可以轻松地使用

StringMap.add

将一张最初为空的地图逐步构建为完整的地图。剩下的唯一问题是您选择与列表中的每个字符串关联的值。

    


1
投票
fold_left

map
我认为这句话可以帮助您理解差异:

想象一下你和很多人一起吃一顿丰盛的晚餐。你正在上菜:你遍历所有的人,然后用装有食物的盘子替换他们的空盘子。这是一个地图操作:桌子上的盘子数量没有改变,但是对于每个盘子,你都做了相同的操作(改变盘子的内容)。 一切完成后,你收集所有脏盘子:这是一个折叠操作,最后,桌子上不再有盘子,但你已经对每个盘子做了一些事情(堆叠它们)并返回文件结果(a一堆脏盘子)。 在这两种情况下,都会系统地应用操作。不同之处在于,Map 保留了当前的“结构”(桌子上的盘子),而 Fold 则删除了结构,并构建了其他东西。”

© www.soinside.com 2019 - 2024. All rights reserved.