doc: update doc/containers, migrate it to mdx

This commit is contained in:
Simon Cruanes 2019-02-02 20:33:51 -06:00
parent 404d74ac43
commit b308680bee
3 changed files with 44 additions and 32 deletions

View file

@ -546,7 +546,7 @@ Some structural types are used throughout the library:
### Extended Documentation ### Extended Documentation
See [the extended documentation](doc/containers.adoc) for more examples. See [the extended documentation](doc/containers.md) for more examples.
</details> </details>

View file

@ -1,12 +1,12 @@
= OCaml-containers = # More about OCaml-containers
:toc: macro
:source-highlighter: pygments
This document contains more information on some modules of Containers. This document contains more information on some modules of Containers.
toc::[] ```ocaml
# #require "containers";;
```
== Hash combinators: `CCHash` ## Hash combinators: `CCHash`
Although OCaml provides polymorphic hash tables (`('a,'b) Hashtbl.t`) Although OCaml provides polymorphic hash tables (`('a,'b) Hashtbl.t`)
using the polymorphic equality `(=)` and hash `Hashtbl.hash`, it is often using the polymorphic equality `(=)` and hash `Hashtbl.hash`, it is often
@ -15,63 +15,67 @@ with custom equality and hash functions.
`CCHash` provides combinators for writing hash functions: `CCHash` provides combinators for writing hash functions:
[source,OCaml] ```ocaml
----
# module H = CCHash;; # module H = CCHash;;
module H = CCHash
# let hash1 : (int * bool) list H.t = H.(list (pair int bool));; # let hash1 : (int * bool) list H.t = H.(list (pair int bool));;
val hash1 : (int * bool) list H.t = <fun>
```
```ocaml non-deterministic=output
# hash1 [1, true; 2, false; 3, true];; # hash1 [1, true; 2, false; 3, true];;
- : int = 636041136 - : int = 636041136
(* the function hashes the whole value, can be costly *)
# hash1 CCList.(1 -- 1000 |> map (fun i->i, i mod 2 = 0));; # hash1 CCList.(1 -- 1000 |> map (fun i->i, i mod 2 = 0));;
- : int = 845685523 - : int = 845685523
# hash1 CCList.(1 -- 1001 |> map (fun i->i, i mod 2 = 0));; # hash1 CCList.(1 -- 1001 |> map (fun i->i, i mod 2 = 0));;
- : int = 381026697 - : int = 381026697
---- ```
The polymorphic hash function is still present, as `CCHash.poly`. The polymorphic hash function is still present, as `CCHash.poly`.
The functions `CCHash.list_comm` and `CCHash.array_comm` allow to hash The functions `CCHash.list_comm` and `CCHash.array_comm` allow to hash
lists and arrays while ignoring the order of elements: all permutations lists and arrays while ignoring the order of elements: all permutations
of the input will have the same hash. of the input will have the same hash.
## Parser Combinator: `CCParse`
== Parser Combinator: `CCParse`
:toc: macro
:source-highlighter: pygments
The module `CCParse` defines basic parser combinators on strings. The module `CCParse` defines basic parser combinators on strings.
Adapting https://github.com/inhabitedtype/angstrom#usage[angstrom's tutorial example] gives the following snippet. Adapting [angstrom's tutorial example](https://github.com/inhabitedtype/angstrom#usage)
gives the following snippet.
Note that backtracking is explicit in `CCParse`, hence Note that backtracking is explicit in `CCParse`, hence
the use of `try_` to allow it in some places. the use of `try_` to allow it in some places.
Explicit memoization with `memo` and `fix_memo` is also possible. Explicit memoization with `memo` and `fix_memo` is also possible.
[source,OCaml] ```ocaml
---- open CCParse.Infix
open CCParse.Infix;; module P = CCParse
module P = CCParse;;
let parens p = P.try_ (P.char '(') *> p <* P.char ')' ;; let parens p = P.try_ (P.char '(') *> p <* P.char ')'
let add = P.char '+' *> P.return (+) ;; let add = P.char '+' *> P.return (+)
let sub = P.char '-' *> P.return (-) ;; let sub = P.char '-' *> P.return (-)
let mul = P.char '*' *> P.return ( * ) ;; let mul = P.char '*' *> P.return ( * )
let div = P.char '/' *> P.return ( / ) ;; let div = P.char '/' *> P.return ( / )
let integer = let integer =
P.chars1_if (function '0'..'9'->true|_->false) >|= int_of_string ;; P.chars1_if (function '0'..'9'->true|_->false) >|= int_of_string
let chainl1 e op = let chainl1 e op =
P.fix (fun r -> P.fix (fun r ->
e >>= fun x -> P.try_ (op <*> P.return x <*> r) <|> P.return x) ;; e >>= fun x -> P.try_ (op <*> P.return x <*> r) <|> P.return x)
let expr : int P.t = let expr : int P.t =
P.fix (fun expr -> P.fix (fun expr ->
let factor = parens expr <|> integer in let factor = parens expr <|> integer in
let term = chainl1 factor (mul <|> div) in let term = chainl1 factor (mul <|> div) in
chainl1 term (add <|> sub)) ;; chainl1 term (add <|> sub))
```
P.parse_string expr "4*1+2";; (* Ok 6 *) Now we can parse strings using `expr`:
P.parse_string expr "4*(1+2)";; (* Ok 12 *)
```ocaml
# P.parse_string expr "4*1+2";; (* Ok 6 *)
- : int P.or_error = Result.Ok 6
# P.parse_string expr "4*(1+2)";; (* Ok 12 *)
- : int P.or_error = Result.Ok 12
```
----

8
doc/dune Normal file
View file

@ -0,0 +1,8 @@
(alias
(name runtest)
(deps containers.md)
(action (progn
(run mdx test %{deps})
(diff? %{deps} %{deps}.corrected))))