Ocaml 如何使用List.fold_left?

Ocaml 如何使用List.fold_left?,ocaml,Ocaml,我仍在努力理解左折叠是如何工作的。它是否像list.iter那样遍历列表?还是我的代码有其他问题?我认为e是列表中的元素(因此它是一个元组),fst e取元组中的第一个元素,snd e取元组中的第二个元素 let rec pow x n = if n < 0 then 0 else if n = 0 then 1 else x * pow x (n - 1);; let polynomial lst =

我仍在努力理解左折叠是如何工作的。它是否像
list.iter
那样遍历列表?还是我的代码有其他问题?我认为e是列表中的元素(因此它是一个元组),
fst e
取元组中的第一个元素,
snd e
取元组中的第二个元素

let rec pow x n = 
    if n < 0 then
        0
    else if n = 0 then
        1
    else 
        x * pow x (n - 1);;    

let polynomial lst = function
    | x -> List.fold_left (fun e -> (fst e) * (pow x (snd e))) 1 lst;;
让rec pow x n=
如果n<0,则
0
否则,如果n=0,则
1.
其他的
x*功率x(n-1);;
设多项式lst=函数
|x->List.fold_左(fune e->(fst e)*(pow x(snd e)))1lst;;
lst是一个元组列表,其中每个元组有两个整数并构成一个多项式函数,因此多项式应该返回一个函数。因此,应该发生的一个例子是

# let f = polynomial [3, 3; -2, 1; 5, 0];;
val f : int -> int = <fun>
# f 2;; (* f is the polynomial function f(x) = 3x^3 + (-2)x + 5 *)
- : int = 25
#设f=多项式[3,3;-2,1;5,0];;
val f:int->int=
#f2;;(*f是多项式函数f(x)=3x^3+(-2)x+5*)
-:int=25
但是我收到了这个错误信息

错误:此表达式的类型为int,但表达式的类型应为'a->int*int'


List.fold_left
确实在一个列表上迭代,将值从一个调用传递到另一个调用,这基本上就像一个,只有一个bucket,在每次迭代中,您可以查看bucket,获取其中的任何内容并放入新的内容

更正式地说,
fold_left f init元素具有类型

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
它有三个参数,函数
f
,初始值
init
,以及
元素列表。函数
f
元素的每个元素
x
调用为
f acc x
,其中
acc
init
,如果
x
是列表的第一个元素,或者是先前调用
f
返回的结果。回到我们的类比,它要么是初始空桶,要么是链中上一次调用传递的桶

在您的案例中,bucket的角色是所有术语的最终总和。最初,它是空的,然后每个新术语计算
(fst e)*(pow x(snd e))
,并将其添加到存储桶中,以便在最后得到所有术语的总和

let polynomial coeffs x = 
  List.fold_left (fun sum (k,r) -> sum + k * pow x r) 0 coeffs
请注意,我没有使用
fst
snd
访问该对的元素,而是直接在参数列表中解构元组。这使得代码更容易理解和缩短

应用于每个步骤的函数有两个参数,
sum
是bucket(通常称为“累加器”)和列表元素,在我们的例子中是一对
(k,r)
。我们将
k
乘以提升到幂
r
x
变量的值,然后将结果添加到累加器中

对于具有命令式思维的人来说,以下伪代码1可能比桶旅类比更具洞察力:

def fold_left(user_func, init, elements):
    acc = init
    for elt in elts:
       acc = user_func(acc, elt)
    return acc


1) 与Python的任何相似之处纯粹是巧合:)

列表。fold_left
确实在列表上迭代,将值从一个调用传递到另一个调用,这基本上就像一个,只有一个bucket,在每次迭代中,您可以查看bucket,获取其中的任何内容并放入新的内容

更正式地说,
fold_left f init元素具有类型

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
它有三个参数,函数
f
,初始值
init
,以及
元素列表。函数
f
元素的每个元素
x
调用为
f acc x
,其中
acc
init
,如果
x
是列表的第一个元素,或者是先前调用
f
返回的结果。回到我们的类比,它要么是初始空桶,要么是链中上一次调用传递的桶

在您的案例中,bucket的角色是所有术语的最终总和。最初,它是空的,然后每个新术语计算
(fst e)*(pow x(snd e))
,并将其添加到存储桶中,以便在最后得到所有术语的总和

let polynomial coeffs x = 
  List.fold_left (fun sum (k,r) -> sum + k * pow x r) 0 coeffs
请注意,我没有使用
fst
snd
访问该对的元素,而是直接在参数列表中解构元组。这使得代码更容易理解和缩短

应用于每个步骤的函数有两个参数,
sum
是bucket(通常称为“累加器”)和列表元素,在我们的例子中是一对
(k,r)
。我们将
k
乘以提升到幂
r
x
变量的值,然后将结果添加到累加器中

对于具有命令式思维的人来说,以下伪代码1可能比桶旅类比更具洞察力:

def fold_left(user_func, init, elements):
    acc = init
    for elt in elts:
       acc = user_func(acc, elt)
    return acc


1) 与Python的任何相似之处纯粹是巧合:)

因此0是函数的起始值,并且(fun sum(k,r)->sum+k*pow x r)将其相加?如果我没有弄错的话。不客气,我已经添加了一个详细的
fold_left
函数说明,因为官方手册中似乎没有详细描述它。所以0是函数的起始值,并且(fun sum(k,r)->sum+k*pow x r)添加了它?如果我没有弄错的话。不客气,我已经添加了一个关于
左折
功能的详细说明,因为官方手册中似乎没有详细描述它。