Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List.sum in Core, don't understand containers

I'm trying to understand List.sum from Jane streets core. I got it to work on a simple list of integers, but don't understand the concepts of Core's containers, and find the api documentation to terse to understand. Here's some code that works:

#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

Why do I have to use module Int and the identity function. [1;2;3] already provides a type of int list. Is there any good information about the design ideas behind Core?

like image 746
bart van deenen Avatar asked Nov 01 '25 05:11

bart van deenen


1 Answers

The module provides the means of summing the values in question. The f provides a transformation function from the type of elements in the list to the type of elements you want to sum.

If all you want want to do is sum the integers in a list, then the summation function desired is in the Int module (thus we need module Int) and the transformation function is just ident (because we needn't transform the values at all).

However, what if you wanted obtain a sum of integers, but starting with a list of strings representing integers? Then we would have

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

i.e., if we want to sum using the module Int over a list of strings, then we'll first need a function that will convert each value of type string to a value of type int. Thus:

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

This is pretty verbose, but it gives us a lot of flexibility! Imagine trying to sum using a different commutative operation, perhaps over a particular field in a record.

However, this is not the idiomatic way to sum a list of integers in OCaml. List.sum is a specific function which the List module "inherits" by virtue of it satisfying the a container interface used in the library design of Base (which provides the basic functionality of Core. The reason this function is relatively complex to use is because it is the result of a highly generalized design over algebraic structures (in this case, over collections of elements which can be transformed in elements which have a commutative operation defined over them).

For mundane integer summation, OCamlers just use a simple fold:

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

One good place to look for some insight into the design decisions behind Core is https://dev.realworldocaml.org/ . Another good resource is the Janestreet tech blog. You might also consult the Base repo (https://github.com/janestreet/base) or post a question asking for more specific details on the design philosophy in https://discuss.ocaml.org/

Janestreet's libraries have been notoriously opaque to newcomers, but they are getting a lot better, and the community will be happy to help you learn.

Tho the documentation is terse, it is very expressive. In particular, it tends to rely on the types to carry much of the weight, which means the code is largely self-documenting. It takes some practice to learn to read the types well, but this is well worth the effort, imo, and carries its own rewards!

like image 160
Shon Avatar answered Nov 04 '25 20:11

Shon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!