我仍在尝试了解fold_left
的工作原理。是否像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;;
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
但是我收到此错误消息
“错误:此表达式的类型为int,但预期类型为'a-> int * int”。
答案 0 :(得分:0)
List.fold_left
实际上是遍历一个列表,将值从一个调用传递到另一个,基本上就像bucket brigade一样,只有一个存储桶,在每次迭代中您都可以查看存储桶,拿东西在那里,放一些新东西。
更正式地说,fold_left f init elements
具有类型
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
,它带有三个参数,即函数f
,初始值init
和elements
的列表。为{{1}的每个元素f
调用函数x
为elements
,其中f acc x
是acc
,如果init
是列表的第一个元素或上一次调用x
返回的结果。回到我们的类比中,它要么是初始的空桶,要么是链中上一个调用传递的桶。
在您的情况下,存储桶的作用是所有条件的最终总和。最初,它为空,然后每个新术语计算f
并将其添加到存储桶中,以便最后您将获得所有术语的总和,
(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
就我们而言。我们将(k,r)
乘以k
变量的值并乘以幂x
,然后将结果加到累加器上。
对于有命令性思维方式的人,以下伪代码 1 可能比水桶大队的类比更具洞察力:
r
1 )与Python的任何相似之处纯属巧合:)