List.fold参数的顺序

时间:2019-04-26 08:12:28

标签: .net functional-programming f#

嗨,我试图理解以下代码。该代码的目的是计算素数出现的次数。 factors函数只是查找给定数字的素因数。

let smallArray = Array.Parallel.init 5 factors;;

let checkMap key map =
    match Map.tryFind key map with
    | Some i -> i
    | None -> 0

let incr map (key:int) = Map.add key ((checkMap key map) + 1) map

Array.fold (List.fold incr) Map.empty smallArray;; 

我卡住的地方是代码的最后一行。我不知道它是否先执行Array.fold或List.fold,但我猜应该是List.fold。下一步是将函数incr应用于小数组,并将其放入一个空的映射中,但是函数incr接受2个参数,据我所知,我们仅为其提供一个映射?有人可以解释一下吗?

1 个答案:

答案 0 :(得分:1)

首先让我们总结一下此处涉及的功能类型:

List.fold : ('State -> 'T -> 'State) -> 'State -> 'T list -> 'State
Array.fold : ('State -> 'T -> 'State) -> 'State -> 'T [] -> 'State
incr : Map<int, int> -> int -> Map<int, int>

从类型上我们可以看到,List.fold接受与incr形状相同的函数,并接受两个参数并返回与第一个参数相同类型的值。在替换推断的类型之前,将incr应用于List.fold将产生具有以下类型的部分应用的函数:

(List.fold incr) : 'State -> 'T list -> 'State

,在将'State'T替换为可以从incr的应用程序推断出的类型之后,我们得到:

(List.fold incr) : Map<int, int> -> int list -> Map<int, int>

这又与incr具有相同的形状,唯一的区别是int的第二个incr自变量在此处是int list。并且由于Array.foldList.fold具有相同的基本形状,因此我们可以像上述(List.fold incr)一样使用incr作为Array.fold的第一个参数。

Array.fold (List.fold incr)(如果部分应用)将产生以下类型:

(Array.fold (List.fold incr)) : Map<int, int> -> int list [] -> Map<int, int>
然后将

Map.emptysmallArray分别应用于最后一个参数作为初始值和要折叠的集合,以便:

  • Array.foldsmallArray叠在(List.fold incr)
  • List.fold incr依次折叠int list中的每个smallArray
  • incr将其结果累积到Map<int, int>中,该结果源自传递给Map.empty的初始Array.fold值。