List.fold порядок аргументов - PullRequest
1 голос
/ 26 апреля 2019

Привет, я пытаюсь понять следующий код.Цель этого кода - подсчитать, сколько раз появляется главный фактор.Функция 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 Ответ

1 голос
/ 26 апреля 2019

Давайте сначала суммируем типы функций, задействованных здесь:

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.
...