A port of the Scrap Your Boilerplate library to BER MetaOCaml with modular implicits.
Generic programming libraries like Scrap Your Boilerplate make it possible to express a variety of traversals succinctly. However, the resulting code is often considerably slower (10-20x) than equivalent handwritten code. This overhead is largely a result of various forms of abstraction and higher-order polymorphism, and can be eliminated by using MetaOCaml's staging facilities to instantiate generic functions to type-specialised code.
The draft paper Staging Generic Programming (to appear at PEPM 2016) explains the design of this library in detail.
opam switch 4.02.1+modular-implicits-ber
opam pin add syb https://github.com/yallop/metaocaml-syb.git
The following examples assume that you have loaded the package and brought the instances into scope:
# #require "syb";;
# open Syb.Instances;;
Apply not
to every bool
within a larger structure:
# Syb.(everywhere (mkT not)) [[true], 1; [], 2; [true; false], 3];;
- : (bool list * int) list = [([false], 1); ([], 2); ([false; true], 3)]
Instantiate a version of the above traversal specialized for not
and (bool list * int) list
:
# let f : (bool list * int) list -> (bool list * int) list =
Syb.(instantiateT (everywhere_ (mkT_ (fun x -> .<not .~x>.))));;
val f : (bool list * int) list -> (bool list * int) list = <fun>
Show the code generated for the type-specialized traversal:
# let f_code : ((bool list * int) list -> (bool list * int) list) code =
Syb.(generateT (everywhere_ (mkT_ (fun x -> .<not .~x>.))));;
val f_code : ((bool list * int) list -> (bool list * int) list) code = .<
...
>.