From 801f0595325bfbe3a56496702c03197dd7dfc40b Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 17 Feb 2017 14:20:45 +0100 Subject: [PATCH] add some doc --- README.adoc | 42 ++++--------------------- doc/containers.adoc | 77 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 doc/containers.adoc diff --git a/README.adoc b/README.adoc index 1578eaa8..23e5502b 100644 --- a/README.adoc +++ b/README.adoc @@ -92,9 +92,11 @@ and <> for a gentle introduction. == Documentation In general, see http://c-cube.github.io/ocaml-containers/ or -http://cedeela.fr/~simon/software/containers +http://cedeela.fr/~simon/software/containers for the **API documentation**. -by version: +Some examples can be found link:doc/containers.adoc[there]. + +API documentation by version: - http://c-cube.github.io/ocaml-containers/dev/[dev branch] - http://c-cube.github.io/ocaml-containers/1.0/[1.0] @@ -433,38 +435,6 @@ printer:: `'a printer = Format.formatter -> 'a -> unit` is a pretty-printer to be used with the standard module `Format`. In particular, in many cases, `"foo: %a" Foo.print foo` will type-check. -=== Parser Combinator +=== Extended Documentation -The module `CCParse` defines basic parser combinators on strings. -Adapting https://github.com/inhabitedtype/angstrom#usage[angstrom's tutorial example] gives the following snippet. -Note that backtracking is explicit in `CCParse`, hence -the use of `try_` to allow it in some places. -Explicit memoization with `memo` and `fix_memo` is also possible. - -[source,OCaml] ----- -open CCParse.Infix;; -module P = CCParse;; - -let parens p = P.try_ (P.char '(') *> p <* P.char ')' ;; -let add = P.char '+' *> P.return (+) ;; -let sub = P.char '-' *> P.return (-) ;; -let mul = P.char '*' *> P.return ( * ) ;; -let div = P.char '/' *> P.return ( / ) ;; -let integer = - P.chars1_if (function '0'..'9'->true|_->false) >|= int_of_string ;; - -let chainl1 e op = - P.fix (fun r -> - e >>= fun x -> P.try_ (op <*> P.return x <*> r) <|> P.return x) ;; - -let expr : int P.t = - P.fix (fun expr -> - let factor = parens expr <|> integer in - let term = chainl1 factor (mul <|> div) in - chainl1 term (add <|> sub)) ;; - -P.parse_string expr "4*1+2";; (* Ok 6 *) -P.parse_string expr "4*(1+2)";; (* Ok 12 *) - ----- +See link:doc/containers.adoc[the extended documentation] for more examples. diff --git a/doc/containers.adoc b/doc/containers.adoc new file mode 100644 index 00000000..e6c564c6 --- /dev/null +++ b/doc/containers.adoc @@ -0,0 +1,77 @@ += OCaml-containers = +:toc: macro +:source-highlighter: pygments + +This document contains more information on some modules of Containers. + +toc::[] + +== Hash combinators: `CCHash` + +Although OCaml provides polymorphic hash tables (`('a,'b) Hashtbl.t`) +using the polymorphic equality `(=)` and hash `Hashtbl.hash`, it is often +safer and more efficient to use `Hashtbl.Make` (or the extended `CCHashtbl.Make`) +with custom equality and hash functions. + +`CCHash` provides combinators for writing hash functions: + +[source,OCaml] +---- +# module H = CCHash;; + +# let hash1 : (int * bool) list H.t = H.(list (pair int bool));; + +# hash1 [1, true; 2, false; 3, true];; +- : int = 636041136 + +(* the function hashes the whole value, can be costly *) +# hash1 CCList.(1 -- 1000 |> map (fun i->i, i mod 2 = 0));; +- : int = 845685523 +# hash1 CCList.(1 -- 1001 |> map (fun i->i, i mod 2 = 0));; +- : int = 381026697 +---- + +The polymorphic hash function is still present, as `CCHash.poly`. +The functions `CCHash.list_comm` and `CCHash.array_comm` allow to hash +lists and arrays while ignoring the order of elements: all permutations +of the input will have the same hash. + + + +== Parser Combinator: `CCParse` +:toc: macro +:source-highlighter: pygments + +The module `CCParse` defines basic parser combinators on strings. +Adapting https://github.com/inhabitedtype/angstrom#usage[angstrom's tutorial example] gives the following snippet. +Note that backtracking is explicit in `CCParse`, hence +the use of `try_` to allow it in some places. +Explicit memoization with `memo` and `fix_memo` is also possible. + +[source,OCaml] +---- +open CCParse.Infix;; +module P = CCParse;; + +let parens p = P.try_ (P.char '(') *> p <* P.char ')' ;; +let add = P.char '+' *> P.return (+) ;; +let sub = P.char '-' *> P.return (-) ;; +let mul = P.char '*' *> P.return ( * ) ;; +let div = P.char '/' *> P.return ( / ) ;; +let integer = + P.chars1_if (function '0'..'9'->true|_->false) >|= int_of_string ;; + +let chainl1 e op = + P.fix (fun r -> + e >>= fun x -> P.try_ (op <*> P.return x <*> r) <|> P.return x) ;; + +let expr : int P.t = + P.fix (fun expr -> + let factor = parens expr <|> integer in + let term = chainl1 factor (mul <|> div) in + chainl1 term (add <|> sub)) ;; + +P.parse_string expr "4*1+2";; (* Ok 6 *) +P.parse_string expr "4*(1+2)";; (* Ok 12 *) + +----