Давайте сначала суммируем типы функций, задействованных здесь:
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.fold
имеет ту же основную форму, что и List.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.empty
и smallArray
затем применяются к последним аргументам в качестве начального значения и коллекции для сворачивания, соответственно, так что:
Array.fold
складывается smallArray
с (List.fold incr)
List.fold incr
по очереди сгибается над каждым int list
in smallArray
incr
накапливает свои результаты в Map<int, int>
, полученном из начального значения Map.empty
, переданного в Array.fold
.