List.sum в Core, не понимаю, контейнеры - PullRequest
3 голосов
/ 05 мая 2019

Я пытаюсь понять List.sum из ядра улиц Джейн. Я заставил его работать с простым списком целых чисел, но я не понимаю концепции контейнеров Core и нашел краткую для понимания документацию по API. Вот код, который работает:

#require "core";;
open Core;;
List.sum (module Int) [1;2;3] ~f:ident;;
- : int = 6


#show List.sum;;

val sum :
  (module Base__.Container_intf.Summable with type t = 'sum) ->
  'a list -> f:('a -> 'sum) -> 'sum

Почему я должен использовать module Int и функцию идентификации. [1;2;3] уже предоставляет тип int list. Есть ли какая-нибудь хорошая информация об идеях дизайна, лежащих в основе Core?

1 Ответ

3 голосов
/ 05 мая 2019

Модуль предоставляет средства суммирования рассматриваемых значений. f предоставляет функцию преобразования из типа элементов в списке в тип элементов, которые вы хотите суммировать.

Если все, что вы хотите сделать, это суммировать целые числа в списке, тогда требуемая функция суммирования находится в модуле Int (таким образом, нам нужно module Int), а функция преобразования - просто ident (потому что мы не нужно преобразовывать значения вообще).

Однако, что если вы хотите получить сумму целых чисел, но начиная со списка строк, представляющих целые числа? Тогда у нас будет

utop # List.sum (module Int) ["1";"2";"3";"4"];;
- : f:(string -> int) -> int = <fun>

Т.е., если мы хотим суммировать, используя module Int по списку строк, то сначала нам понадобится функция, которая преобразует каждое значение типа string в значение типа int. Таким образом:

utop # List.sum (module Int) ["1";"2";"3";"4"] ~f:Int.of_string;;
- : int = 10

Это довольно многословно, но дает нам большую гибкость! Представьте себе попытку суммирования с использованием другой коммутативной операции, возможно, по определенному полю в записи.

Однако это не идиоматический способ суммировать список целых чисел в OCaml. List.sum - это особая функция, которую модуль List «наследует» благодаря тому, что она удовлетворяет интерфейсу контейнера, используемому в проекте библиотеки Base (который обеспечивает базовую функциональность Core. Причина, по которой эта функция Относительно сложным в использовании является то, что он является результатом сильно обобщенного проектирования над алгебраическими структурами (в данном случае, над наборами элементов, которые могут быть преобразованы в элементы, для которых определена коммутативная операция над ними). ​​

Для мирского суммирования, OCamlers просто использует простую складку:

utop # List.fold [1;2;3;4] ~init:0 ~f:(+);;
- : int = 10

Хорошее место, где можно взглянуть на проектные решения, стоящие за Core, - это https://dev.realworldocaml.org/. Еще один хороший ресурс - технический блог Janestreet . Вы также можете проконсультироваться с репозиторием Base (https://github.com/janestreet/base) или опубликовать вопрос с более подробной информацией о философии дизайна в https://discuss.ocaml.org/

Библиотеки Janestreet были заведомо непрозрачны для новичков, но они становятся намного лучше, и сообщество будет радо помочь вам учиться.

То, что документация лаконична, очень выразительна. В частности, он имеет тенденцию полагаться на типы, которые несут большую часть веса, что означает, что код в значительной степени самодокументируется. Требуется некоторая практика, чтобы научиться хорошо читать шрифты, но это того стоит, imo, и несет свои собственные награды!

...